ASP.NET Core 6中ISessionStore实现报错:无法从根提供程序解析作用域服务
问题解决:无法从根提供者解析ISessionStore作用域服务
错误原因
- 服务生命周期不匹配:ASP.NET Core的Session中间件在应用启动阶段(根服务提供者环境,无请求作用域)会尝试获取
ISessionStore实例,但你用AddScoped注册的服务仅能在请求作用域内被解析,根容器无法访问作用域服务,因此抛出错误。 - 接口实现不兼容:自定义的
SQLServersSessionStore中Create方法的参数与框架定义的Microsoft.AspNetCore.Session.ISessionStore接口不匹配(框架要求第一个参数是sessionKey而非userId),会导致框架调用时出现兼容性问题。 - 异步操作未等待:
Create方法中调用SaveChangesAsync()时未使用await,会导致数据库操作未完成就返回,引发数据不一致或异常。
修正步骤
1. 修改服务注册生命周期
在Startup.cs的ConfigureServices方法中,将ISessionStore的注册从Scoped改为Singleton,确保根服务提供者可以解析该服务:
// 替换原有的AddScoped注册 services.AddSingleton<ISessionStore, SQLServersSessionStore>();
2. 修正ISessionStore接口实现
调整SQLServersSessionStore的Create方法,使其符合框架接口定义,并修复异步操作:
// 注入IHttpContextAccessor用于获取当前用户信息(若需要) private readonly AppDbContext _dbContext; private readonly IHttpContextAccessor _httpContextAccessor; public SQLServersSessionStore(AppDbContext dbContext, IHttpContextAccessor httpContextAccessor) { _dbContext = dbContext; _httpContextAccessor = httpContextAccessor; } public async ISession Create(string sessionKey, TimeSpan idleTimeout, TimeSpan absoluteTimeout, Func<bool> tryEstablishSession, bool isNewSessionKey) { var sessionEntity = new SessionEntity { SessionId = sessionKey, // 从当前请求上下文获取用户ID(如需关联用户) UserId = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier), ExpirationDate = DateTimeOffset.UtcNow.Add(idleTimeout) }; _dbContext.Sessions.Add(sessionEntity); // 等待异步数据库操作完成 await _dbContext.SaveChangesAsync(); var session = new Session { Id = sessionKey }; return session; }
3. 确认Session中间件顺序
保持Configure方法中UseSession的位置正确(在UseRouting之前、UseStaticFiles之后),当前配置已符合要求:
app.UseStaticFiles(); app.UseSession(); app.UseRouting();
额外说明
框架的ISessionStore是供Session中间件内部使用的,不要直接在控制器中注入。如果需要操作Session,建议直接通过HttpContext.Session访问,或封装自定义的Session操作服务。
内容的提问来源于stack exchange,提问作者nightwolf555
相关产品推荐
相关产品推荐

