gpt4 book ai didi

c# - Session.SetString 方法抛出异常 "IFeatureCollection has been disposed. Object name: ' Collection'。 "在 ASP.NET Core 3.1 中

转载 作者:行者123 更新时间:2023-12-03 15:43:28 26 4
gpt4 key购买 nike

我有一个用 ASP.NET Core 3.1 编写的项目。
我需要在 Singleton 服务中将数据设置为 Session:

 _session.SetString("some key", "some value");
我从 DI 注入(inject)了 session 对象:
public OperatorService(ILogger<OperatorService> logger, 
ISession session,
IOptions<AppSettings> options)
{
this._session = session;
this._logger = logger;
this._appSettings = options.Value;
}
我调用 my 方法如下:
public void ChangeOperatorStatus(StatusChangeRequest request)
{
try
{
_session.SetString(request.Key, request.Value);
}
catch (Exception ex)
{
_logger.LogInformation($"Exception while changing status: {ex}");
}
}
但我得到以下异常(exception):
IFeatureCollection has been disposed.\r\nObject name: 'Collection'. 
我在 Startup.cs 的 ConfigureServices 方法中添加了一些代码:
services.AddHttpContextAccessor();

services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(20);
options.Cookie.HttpOnly = true;
})
.AddDistributedMemoryCache();
我添加了 app.UseSession();到 Startup.cs 的 Configure 方法。
我试过 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();我从 httpContextAccessor.HttpContext.Session 获得 session 但我得到同样的错误。
请帮帮我,谢谢。

最佳答案

HttpContext 是单个请求的上下文。它提供对单个请求的请求、响应属性等的访问。你不能缓存它,一旦请求结束它就会失效。

session 是另一个短暂的东西——它的存在时间与单个用户 session 一样长。 Web 应用程序的每个用户至少有一个 session 。在单例中缓存其中一个 session 可以保证

  • 一段时间后,当 session 到期和
  • 时,引用将失效。
  • 单例将仅使用该用户的值,而忽略其他所有人的值。这本身就是一个错误,也是入侵应用程序的好方法。
  • 如果管理员登录,则 Session 对象可能会在接下来的 20、30 或 60 分钟内将管理员的设置应用到所有人。

  • 这就是为什么使用 Session 对每个请求的中间件有意义,而不是 Singleton 服务。

    HttpContext的正确使用

    Session 只能通过请求的上下文到达,所以获取正确的 session 就意味着获取正确的 HttpContext。 David Fowler's ASP.NET Core Guidance 中解释了执行此操作的正确方法。 :

    ❌ BAD This example stores the HttpContext in a field then attempts to use it later.


        private readonly HttpContext _context;
    public MyType(IHttpContextAccessor accessor)
    {
    _context = accessor.HttpContext;
    }
    public void CheckAdmin()
    {
    if (!_context.User.IsInRole("admin"))
    {
    throw new UnauthorizedAccessException("The current user isn't an admin");
    }
    }

    ✅ GOOD This example stores the IHttpContextAccesor itself in a field and uses the HttpContext field at the correct time (checking for null).


       private readonly IHttpContextAccessor _accessor;
    public MyType(IHttpContextAccessor accessor)
    {
    _accessor = accessor;
    }

    public void CheckAdmin()
    {
    var context = _accessor.HttpContext;
    if (context != null && !context.User.IsInRole("admin"))
    {
    throw new UnauthorizedAccessException("The current user isn't an admin");
    }
    }

    改用 Scoped 服务

    由于 Singleton 不知道要使用哪个 session 。一种选择是简单地将该服务转换为 Scoped 服务。在 ASP.NET Core 中,请求定义了一个范围。这就是 Controller 操作和管道中间件如何为每个请求访问正确的 HttpContext。

    假设服务被操作或中间件使用,也许唯一需要的改变是替换 AddSingleton<ThatService>AddScoped<ThatService>
    扭转局面,或控制反转

    另一种选择是该单例的调用者应向其提供 session 。而不是使用缓存 session ,例如:
    public void SetStatus(string status)
    {
    _session.SetString(SessionKeys.UserStatus, "some value");
    }

    请求 session 或 HttpContext 作为参数:
    public void SetStatus(string status,ISession session)
    {
    session.SetString(SessionKeys.UserStatus, "some value");
    }

    并让调用者将正确的 session 传递给它

    关于c# - Session.SetString 方法抛出异常 "IFeatureCollection has been disposed. Object name: ' Collection'。 "在 ASP.NET Core 3.1 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59963383/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com