本文介绍了ASP.NET Core MVC异步加载会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读官方会话和应用程序状态文档,偶然发现了以下段落:

I have been reading the official Session and application state documentation and have stumbled upon the following paragraph:

ASP.NET Core中的默认会话提供程序将加载会话记录 仅当基础 IDistributedCache 中的数据从 在 TryGetValue 之前显式调用 ISession.LoadAsync 方法, Set Remove 方法.如果不首先调用 LoadAsync ,则 基础会话记录是同步加载的,这可能 可能会影响应用的扩展能力.

The default session provider in ASP.NET Core loads the session record from the underlying IDistributedCache store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. If LoadAsync is not called first, the underlying session record is loaded synchronously, which could potentially impact the ability of the app to scale.

要让应用程序强制执行此模式,请包装 DistributedSessionStore DistributedSession 实现,以及 如果未调用 LoadAsync 方法的版本将引发异常 在 TryGetValue Set 删除之前. 在中注册包装的版本 服务容器.

To have applications enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method is not called before TryGetValue, Set, or Remove. Register the wrapped versions in the services container.

包装本身对我来说不是问题,但要实现它,我需要:

The wrapping itself is not an issue for me, but in order to implement it, I need:

  1. 参考原始实现
  2. 注册包装版本

当前,我创建了以下包装器类:

Currently, I have created the following wrapper class:

public class WrappedDistributedSession : ISession
  {
    private DistributedSession _service;
    private bool loaded = false;

    public WrappedDistributedSession(DistributedSession service)
    {
      _service = service;
    }

    public bool IsAvailable => _service.IsAvailable;

    public string Id => _service.Id;

    public IEnumerable<string> Keys => _service.Keys;

    public void Clear() => _service.Clear();

    public Task CommitAsync() => _service.CommitAsync();

    public Task LoadAsync()
    {
      loaded = true;
      return _service.LoadAsync();
    }

    public void Remove(string key)
    {
      if(loaded)
      {
        _service.Remove(key);
      } else
      {
        throw new Exception();
      }
    }

    public void Set(string key, byte[] value)
    {
      if (loaded)
      {
        _service.Set(key, value);
      }
      else
      {
        throw new Exception();
      }
    }

    public bool TryGetValue(string key, out byte[] value)
    {
      if (loaded)
      {
        return _service.TryGetValue(key, out value);
      }
      else
      {
        throw new Exception();
      }
    }
  }

我已经在Startup.ConfigureServices

services.AddScoped<ISession, WrappedDistributedSession>();

很显然,由于我正在编写此问题,所以我的解决方案不起作用.我在哪里出错了,如何一个"在服务容器中注册包装版本"?

Obviously, since I am writing this question, my solution does not work. Where did I go wrong and how does one "Register the wrapped versions in the services container"?

推荐答案

似乎您也需要实现ISessonStore(这在您引用的文档中实际上已经提到),因为它是在AddSession扩展中注册的唯一一个方法.

It seems you need to implement ISessonStore too (which is actually mentioned in the documentation you quoted), as it's the only one registered in AddSession extension method.

public static IServiceCollection AddSession(this IServiceCollection services)
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    services.AddTransient<ISessionStore, DistributedSessionStore>();
    services.AddDataProtection();
    return services;
}

ISessionStore(因此是DistributedSessionStore)具有Create(请参阅)方法,该方法返回ISession.在这里,您需要返回自定义实现.

ISessionStore (and hence DistributedSessionStore) has a Create (see source) method which returns ISession. Here you need to return your custom implementation.

https://github.com/aspnet/Session/blob/rel/1.1.0/src/Microsoft.AspNetCore.Session/SessionServiceCollectionExtensions.cs#L27-L29

然后您可以使用

services.AddTransient<ISessionStore, AsyncDistributedSessionStore>();

这篇关于ASP.NET Core MVC异步加载会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 23:15