首页 > 解决方案 > 控制器依赖注入中的当前会话

问题描述

在 startup.cs 我有

            services.AddScoped<ISession>();

在控制器中我有

private HttpContect _session;
public AccountController(ISession session)
    {
        _session.session = session;
    }

Isession不是服务,所以不能AddScoped(将导致错误)。我也试过IHttpAccessor,但也没有用(也报错)。我们如何在控制器依赖注入中拥有 HttpContext.sessions?(这甚至是一个好习惯吗?)

标签: asp.net-coreasp.net-core-mvc

解决方案


据我所知,如果您想访问当前会话,我们可以直接在 asp.net 核心 mvc 控制器的 HttpContext 值中使用它。无需自己注入会话。我们只需要在startup.cs中启用会话服务即可。

Asp.net core 会自动调用会话服务,我们可以使用会话方法来获取它。

您可以参考以下资源以了解其工作原理。

  1. 我们应该更新 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.


推荐阅读