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

ASP.NET Core 8:UseWhen中能否直接传递HttpContext替代IHttpContextAccessor?

可行方案:无需IHttpContextAccessor,直接传递UseWhen的HttpContext到自定义文件提供程序

可以实现,这里提供两种适配不同场景的方案:

方案1:分支内按需实例化(最直接,适合单中间件场景)

如果你的自定义文件提供程序仅为特定中间件(比如静态文件中间件)服务,直接在UseWhen的分支管道中,针对每个请求实例化HostResFileProvider并传入当前HttpContext,再绑定到中间件配置即可。

示例代码:

app.UseWhen(context => 
{
    // 替换为你的分支判断逻辑,比如请求路径匹配
    return context.Request.Path.StartsWithSegments("/custom-resources");
}, branchApp => 
{
    branchApp.Use(async (ctx, next) => 
    {
        // 为当前请求创建绑定上下文的自定义提供程序实例
        var customFileProvider = new HostResFileProvider(ctx);

        // 以静态文件中间件为例,配置使用该提供程序
        var staticOptions = new StaticFileOptions
        {
            FileProvider = customFileProvider,
            RequestPath = "/custom-resources"
        };

        branchApp.UseStaticFiles(staticOptions);
        await next();
    });
});

优势:

  • 完全摆脱IHttpContextAccessor,每个请求的提供程序实例仅关联当前请求上下文,无线程安全风险
  • 逻辑直接,无需额外DI配置

方案2:请求作用域注入(适合多服务共享场景)

如果自定义文件提供程序需要被多个服务或中间件共享,可通过请求作用域将当前HttpContext注入,让HostResFileProvider作为作用域服务依赖该上下文。

步骤1:改造自定义文件提供程序

public class HostResFileProvider : IFileProvider
{
    private readonly HttpContext _httpContext;

    public HostResFileProvider(HttpContext httpContext)
    {
        _httpContext = httpContext ?? throw new ArgumentNullException(nameof(httpContext));
    }

    // 实现IFileProvider核心方法
    public IFileInfo GetFileInfo(string subpath)
    {
        // 直接使用_httpContext处理业务,比如根据请求域名返回资源
        var host = _httpContext.Request.Host.Host;
        // ... 你的自定义逻辑
        return new NotFoundFileInfo(subpath);
    }

    public IDirectoryContents GetDirectoryContents(string subpath)
    {
        return new NotFoundDirectoryContents();
    }

    public IChangeToken Watch(string filter)
    {
        return NullChangeToken.Singleton;
    }
}

步骤2:配置DI与分支管道

// 注册为作用域服务(每个请求生成一个实例)
builder.Services.AddScoped<HostResFileProvider>();

app.UseWhen(context => 
{
    return context.Request.Path.StartsWithSegments("/shared-resources");
}, branchApp => 
{
    branchApp.Use(async (ctx, next) => 
    {
        // 将当前请求的HttpContext注入到请求作用域
        var serviceCollection = ctx.RequestServices.GetRequiredService<IServiceCollection>();
        serviceCollection.AddSingleton(ctx);

        await next();
    });

    // 后续依赖HostResFileProvider的服务/中间件会自动获取当前上下文
    branchApp.UseMiddleware<CustomResourceMiddleware>();
});

注意:默认ASP.NET Core DI不会直接提供HttpContext,因此需要在分支管道中手动注册当前请求的上下文实例。

为什么直接传递会失败?

你之前的尝试失败,核心原因是:HostResFileProvider通常在应用启动阶段注册到DI容器(单例/作用域),而UseWhen中的ctx是运行时每个请求才生成的实例——启动阶段没有请求上下文,直接绑定会导致空引用或上下文不匹配。上述方案都是将上下文绑定延迟到请求处理阶段,确保每个请求的上下文都能正确关联到对应的提供程序实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:37:39