You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 6中自定义类使用HttpContextAccessor时HttpContext为空求助

问题:HttpContextAccessor获取HttpContext始终为null

在自定义BLL类UserPermisionConfig中注入IHttpContextAccessor后,初始化成功但HttpContext始终为null,相关代码如下:

Program.cs 代码

builder.Services.AddSingleton<IUserPermissionConfig, UserPermisionConfig>();

builder.Services.AddHttpContextAccessor();

var app = builder.Build();

var setUserPermission = app.Services.GetRequiredService<IUserPermissionConfig>();
setUserPermission.SetUserPermissionsSession(UserConstants.SYSTEM_ID);

UserPermisionConfig 代码

private readonly IHttpContextAccessor _httpContextAccessor;

public UserPermisionConfig(IHttpContextAccessor httpContextAccessor)
{
    _permisionServiceClient = new PermissionServiceClient();

    _httpContextAccessor = httpContextAccessor ?? throw new Exception("Http context accessor is null.");
}

public async Task SetUserPermissionsSession(int systemId)
{
    string userName = _httpContextAccessor.HttpContext.
         User.Identity.Name; //此处HttpContext始终为空
    UserPermissionsModel userPermissionModel = await GetUserPermission(systemId, userName);

    _httpContextAccessor.HttpContext.Session.Set(UserConstants.SESSION_USER_PERMISSIOS, ByteArrayExtensions.ToByteArray(userPermissionModel));
}

问题原因

  1. 启动阶段无请求上下文:你在Program.cs中直接通过app.Services.GetRequiredService()获取实例并调用方法,此时程序处于启动初始化阶段,没有任何HTTP请求正在处理,HttpContext仅在请求管道处理请求的过程中存在,自然无法获取到。
  2. 生命周期不匹配:UserPermisionConfig被注册为Singleton单例服务,而IHttpContextAccessor本质上依赖请求作用域(Scoped)的上下文存储,单例服务依赖Scoped服务会导致上下文无法正确绑定,甚至引发生命周期冲突。

解决方案

1. 调整服务生命周期并移至请求流程中调用

首先将UserPermisionConfig改为Scoped生命周期,确保和请求上下文的作用域匹配,然后在控制器、中间件等请求处理环节调用方法:

修改Program.cs

// 将Singleton改为Scoped
builder.Services.AddScoped<IUserPermissionConfig, UserPermisionConfig>();
builder.Services.AddHttpContextAccessor();

var app = builder.Build();

// 移除启动时直接调用的代码,避免无上下文场景
// var setUserPermission = app.Services.GetRequiredService<IUserPermissionConfig>();
// setUserPermission.SetUserPermissionsSession(UserConstants.SYSTEM_ID);

// 确保启用Session(如果需要操作Session)
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

在控制器中注入调用

public class HomeController : Controller
{
    private readonly IUserPermissionConfig _permissionConfig;

    public HomeController(IUserPermissionConfig permissionConfig)
    {
        _permissionConfig = permissionConfig;
    }

    public async Task<IActionResult> Index()
    {
        // 仅在用户认证后执行
        if (User.Identity.IsAuthenticated)
        {
            await _permissionConfig.SetUserPermissionsSession(UserConstants.SYSTEM_ID);
        }
        return View();
    }
}

2. 使用中间件全局初始化权限

如果需要对每个认证后的请求自动初始化权限,可以编写自定义中间件:

编写中间件类

public class PermissionInitMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IUserPermissionConfig _permissionConfig;

    public PermissionInitMiddleware(RequestDelegate next, IUserPermissionConfig permissionConfig)
    {
        _next = next;
        _permissionConfig = permissionConfig;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 仅在用户已认证时执行权限初始化
        if (context.User.Identity.IsAuthenticated)
        {
            await _permissionConfig.SetUserPermissionsSession(UserConstants.SYSTEM_ID);
        }
        // 继续执行后续中间件
        await _next(context);
    }
}

在Program.cs中注册中间件

builder.Services.AddScoped<IUserPermissionConfig, UserPermisionConfig>();
builder.Services.AddHttpContextAccessor();
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

var app = builder.Build();

app.UseSession();
app.UseAuthentication();
app.UseAuthorization();

// 将权限初始化中间件放在认证之后
app.UseMiddleware<PermissionInitMiddleware>();

app.MapControllers();
app.Run();

内容的提问来源于stack exchange,提问作者So_oP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:15:34