ASP.NET Core中间件中非静态实例变量为何仅被赋值一次?
核心原因:ASP.NET Core 中间件默认为单例生命周期
ASP.NET Core 的自定义中间件默认在应用启动时初始化唯一1个实例,整个应用运行周期内会复用该实例处理所有请求。你定义的_client属于实例字段,会跟随这个唯一的中间件实例存在,第一次请求完成赋值后不会自动重置为null,因此后续所有请求都会复用第一次创建的HttpClient实例。
现有代码存在的可优化点
- 异步方法未加
await:GetClientAsync是返回Task<HttpClient>的异步方法,直接赋值给HttpClient类型的_client会触发编译错误,调用异步方法必须搭配await关键字。 Invoke方法不符合规范:中间件的Invoke/InvokeAsync方法第一个参数必须是HttpContext类型,你代码中用到的context变量也没有定义来源。- 方法参数传递缺失:
GetClientAsync要求传入IHttpClientFactory参数,调用时未传参同样会触发编译错误。
推荐实现方案
IHttpClientFactory本身已经实现了HttpClient生命周期的托管,不需要手动缓存实例,两种常用实现方式如下:
方案1:构造函数初始化(适合全局复用同一个命名客户端)
public class AuthMiddleware { private readonly RequestDelegate _next; private readonly HttpClient _client; // 构造函数仅在应用启动时执行一次,直接完成HttpClient初始化 public AuthMiddleware(RequestDelegate next, IHttpClientFactory clientFactory) { _next = next; _client = clientFactory.CreateClient("TestClient"); } public async Task InvokeAsync(HttpContext context) { // 直接复用已经初始化完成的_client即可 // 此处添加你的业务校验逻辑 await _next(context); } }
方案2:请求级获取客户端(适合需要按请求动态调整客户端的场景)
public class AuthMiddleware { private readonly RequestDelegate _next; public AuthMiddleware(RequestDelegate next) { _next = next; } // IHttpClientFactory从InvokeAsync参数注入,每次请求对应独立的作用域 public async Task InvokeAsync(HttpContext context, IHttpClientFactory clientFactory) { var client = clientFactory.CreateClient("TestClient"); // 此处添加你的业务校验逻辑 await _next(context); } }
内容的提问来源于stack exchange,提问作者AliK
相关产品推荐
相关产品推荐

