简体   繁体   English

ASP.NET Core 3.1 中的 Session.SetString 方法抛出异常“IFeatureCollection 已被处理。对象名称:'Collection'。”

[英]Session.SetString method throws exception "IFeatureCollection has been disposed. Object name: 'Collection'. " in ASP.NET Core 3.1

I have a project written in ASP.NET Core 3.1.我有一个用 ASP.NET Core 3.1 编写的项目。

I need to set data to Session in Singleton service:我需要在 Singleton 服务中将数据设置为 Session:

 _session.SetString("some key", "some value");

I injected the session object from DI:我从 DI 注入了会话对象:

public OperatorService(ILogger<OperatorService> logger, 
                       ISession session,
                       IOptions<AppSettings> options)
{
     this._session = session; 
     this._logger = logger; 
     this._appSettings = options.Value;
}

I calls the my method as below:我调用我的方法如下:

public void ChangeOperatorStatus(StatusChangeRequest request)
{
     try
     {
         _session.SetString(request.Key, request.Value);
     }
     catch (Exception ex)
     {
          _logger.LogInformation($"Exception while changing status: {ex}"); 
     } 
} 

but I get the exception below :但我得到以下异常:

IFeatureCollection has been disposed.\r\nObject name: 'Collection'. 

and I added some code to Startup.cs's ConfigureServices method:我在 Startup.cs 的 ConfigureServices 方法中添加了一些代码:

services.AddHttpContextAccessor();

services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(20);
    options.Cookie.HttpOnly = true;
})
.AddDistributedMemoryCache();

And I added app.UseSession();我添加了app.UseSession(); to the Configure method of Startup.cs.到 Startup.cs 的 Configure 方法。

I trid services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();我尝试了services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); and I get the session from httpContextAccessor.HttpContext.Session but I get the same error.我从httpContextAccessor.HttpContext.Session获得了会话,但我得到了同样的错误。

Please help me, thank you.请帮帮我,谢谢。

An HttpContext is the context of a single request. HttpContext 是单个请求的上下文。 It provides access to the request, response properties etc of that single request.它提供对单个请求的请求、响应属性等的访问。 You can't cache it, it becomes invalid once that request ends.你不能缓存它,一旦请求结束它就无效了。

Session is another transient thing - it lives only as long as a single user session.会话是另一个短暂的东西 - 它只与单个用户会话一样长。 There's at least one session for every user of a web app.网络应用程序的每个用户至少有一个会话。 Caching one of those sessions in a singleton guarantees that在单例中缓存这些会话之一可以保证

  • The reference will become invalid after a while, when the session expires and引用将在一段时间后失效,当会话到期时
  • The singleton will use only that user's values, ignoring everyone else's.单身人士将仅使用该用户的值,而忽略其他所有人的值。 This is a bug in itself, and a great way to hack into an application.这本身就是一个错误,也是入侵应用程序的方法。
  • If an administrator logs in, the Session object may apply the admin's settings alive to everyone for the next 20, 30 or 60 minutes.如果管理员登录,会话对象可能会在接下来的 20、30 或 60 分钟内将管理员的设置活着应用于每个人。

That's why using a Session makes sense for per-request middleware, not Singleton services.这就是为什么使用 Session 对每个请求中间件有意义,而不是单例服务。

Correct usage of HttpContext HttpContext 的正确使用

The Session can only be reached through the request's context, so getting the correct session means getting the correct HttpContext. Session 只能通过请求的上下文访问,因此获取正确的会话意味着获取正确的 HttpContext。 The correct way to do this is explained in David Fowler's ASP.NET Core Guidance : David Fowler 的 ASP.NET Core Guidance 中解释了正确的方法:

❌ BAD This example stores the HttpContext in a field then attempts to use it later. ❌ BAD 此示例将 HttpContext 存储在一个字段中,然后尝试稍后使用它。

    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). ✅ GOOD 此示例将 IHttpContextAccesor 本身存储在一个字段中,并在正确的时间使用 HttpContext 字段(检查是否为空)。

   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");
       }
   }

Use a Scoped service instead改用 Scoped 服务

Since a Singleton can't know what session to use.由于单例无法知道要使用哪个会话。 One option is to simply convert that service to a Scoped service.一种选择是简单地将该服务转换为 Scoped 服务。 In ASP.NET Core, a request defines a scope.在 ASP.NET Core 中,请求定义了一个范围。 That's how controller actions and pipeline middleware get access to the correct HttpContext for each request.这就是控制器操作和管道中间件如何为每个请求访问正确的 HttpContext。

Assuming the service is used by an action or middleware, perhaps the only change needed is to replace AddSingleton<ThatService> with AddScoped<ThatService>假设服务由操作或中间件使用,可能唯一需要的更改是将AddSingleton<ThatService>替换为AddScoped<ThatService>

Turning the tables, or Inversion of Control扭转局面,或控制反转

Another option is for callers of that singleton should provide the session to it.另一种选择是该单身人士的调用者应该向它提供会话。 Instead of using a cached session eg :而不是使用缓存会话,例如:

public void SetStatus(string status)
{
    _session.SetString(SessionKeys.UserStatus, "some value");
}

Ask for the session or HttpContext as a parameter :请求会话或 HttpContext 作为参数:

public void SetStatus(string status,ISession session)
{
    session.SetString(SessionKeys.UserStatus, "some value");
}

And have callers pass the correct session to it并让调用者将正确的会话传递给它

It took me a while to get this fixed.我花了一段时间才解决这个问题。 In my case, it was a 3.1 aspnetcore and it didn't worked until I turn the container function from就我而言,它是一个 3.1 aspnetcore,直到我将容器功能从

public async void OnPost

to

public async Task<IActionResult> OnPost

Looks like the HttpContext was disposed before it was used...看起来 HttpContext 在使用之前已被处理...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 gRPC IFeatureCollection 已被处理。 对象名称:&#39;集合&#39; - gRPC IFeatureCollection has been disposed. Object name: 'Collection' IFeatureCollection 已被处理。 对象名称:&#39;集合&#39;。 从控制器到视图 - IFeatureCollection has been disposed. Object name: 'Collection'. going from controller to view 服务器端 .NET Core 中的 Session.SetString() 产生错误“响应开始后无法建立会话” - Session.SetString() in Server Side .NET Core Produces error "The session cannot be established after the response has started" ASP.NET Boilerplate-“ ObjectContext实例已被处置”异常 - ASP.NET Boilerplate - “The ObjectContext instance has been disposed” exception System.ObjectDisposedException:无法访问已处理的对象,ASP.NET Core 3.1 - System.ObjectDisposedException: Cannot access a disposed object, ASP.NET Core 3.1 最终使用ObjectDataSource.Select()方法会导致异常“由于DbContext已被处置,因此无法完成该操作。” - Usage of ObjectDataSource.Select() method eventually results to exception “The operation cannot be completed because the DbContext has been disposed.” 上下文已被处理。 执行异步 - Context has been disposed. Execute Async 在 ASP.NET Core 3.1 中创建会话 - Creating a session in ASP.NET Core 3.1 asp.net core 3.1中的会话管理 - Session Management in asp.net core 3.1 Asp.net 核心标识方法 FindByEmailAsync 抛出异常 - Asp.net core identity method FindByEmailAsync throws exception
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM