asp.net-core - 控制器依赖注入中的当前会话
问题描述
在 startup.cs 我有
services.AddScoped<ISession>();
在控制器中我有
private HttpContect _session;
public AccountController(ISession session)
{
_session.session = session;
}
但Isession
不是服务,所以不能AddScoped
(将导致错误)。我也试过IHttpAccessor
,但也没有用(也报错)。我们如何在控制器依赖注入中拥有 HttpContext.sessions?(这甚至是一个好习惯吗?)
解决方案
据我所知,如果您想访问当前会话,我们可以直接在 asp.net 核心 mvc 控制器的 HttpContext 值中使用它。无需自己注入会话。我们只需要在startup.cs中启用会话服务即可。
Asp.net core 会自动调用会话服务,我们可以使用会话方法来获取它。
您可以参考以下资源以了解其工作原理。
我们应该更新 startup.cs 的 ConfigureServices 方法添加这个:
services.AddSession();
这个 AddSession 方法的源代码是:
public static IServiceCollection AddSession(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.TryAddTransient<ISessionStore, DistributedSessionStore>();
services.AddDataProtection();
return services;
}
你会发现它添加了 ISessionStore,ISessionStore 用于创建会话存储。
2.我们应该将 UseSession() 添加到 startup.cs 的 Configure(IApplicationBulider app, ...) 方法中:
app.UseSession();
源代码如下:
public async Task Invoke(HttpContext context)
{
var isNewSessionKey = false;
Func<bool> tryEstablishSession = ReturnTrue;
var cookieValue = context.Request.Cookies[_options.Cookie.Name!];
var sessionKey = CookieProtection.Unprotect(_dataProtector, cookieValue, _logger);
if (string.IsNullOrWhiteSpace(sessionKey) || sessionKey.Length != SessionKeyLength)
{
// No valid cookie, new session.
var guidBytes = new byte[16];
RandomNumberGenerator.Fill(guidBytes);
sessionKey = new Guid(guidBytes).ToString();
cookieValue = CookieProtection.Protect(_dataProtector, sessionKey);
var establisher = new SessionEstablisher(context, cookieValue, _options);
tryEstablishSession = establisher.TryEstablishSession;
isNewSessionKey = true;
}
var feature = new SessionFeature();
feature.Session = _sessionStore.Create(sessionKey, _options.IdleTimeout, _options.IOTimeout, tryEstablishSession, isNewSessionKey);
context.Features.Set<ISessionFeature>(feature);
try
{
await _next(context);
}
finally
{
context.Features.Set<ISessionFeature?>(null);
if (feature.Session != null)
{
try
{
await feature.Session.CommitAsync();
}
catch (OperationCanceledException)
{
_logger.SessionCommitCanceled();
}
catch (Exception ex)
{
_logger.ErrorClosingTheSession(ex);
}
}
}
}
您会发现它读取数据并将其设置为 httpcontext。
因此,需要并且没有将会话注入控制器的内置方法。我们可以通过 usingHttpContext
或注入IHttpContextAccessor
并使用它的HttpContext
.