.NET Core 6 WebAPI如何全局复用请求头初始化的UserDetails对象
解决方案:在.NET Core 6 WebAPI中复用请求级别的UserDetails实例
问题分析
你需要实现的是请求级别的UserDetails复用,而非全局单例(全局单例会导致多请求间数据混乱)。之前的代码存在几个核心问题:
- 中间件内新建了独立的UserDetails实例,未关联到DI容器的Scoped实例
- Program.cs中错误地获取中间件实例并调用InvokeAsync,不符合中间件的正确使用逻辑
正确实现步骤
1. 保留UserDetails类
public class UserDetails { public int UserId { get; set; } public string UserName { get; set; } }
2. 修改中间件:从DI获取Scoped实例并赋值
中间件的核心逻辑是拿到当前请求的Scoped UserDetails实例,从HttpContext读取请求头填充属性:
public class UserDetailsMiddleware { private readonly RequestDelegate _next; public UserDetailsMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext httpContext, UserDetails userDetails) { // 安全解析UserId(避免非数字格式的请求头导致异常) if (int.TryParse(httpContext.Request.Headers["userid"], out var userId)) { userDetails.UserId = userId; } userDetails.UserName = httpContext.Request.Headers["username"]; // 继续执行后续中间件 await _next(httpContext); } }
3. 正确配置Program.cs
- 将UserDetails注册为Scoped(每个请求生成一个实例,保证请求内复用、请求间隔离)
- 按顺序注册中间件(需放在业务中间件之前)
var builder = WebApplication.CreateBuilder(args); // 注册Scoped生命周期的UserDetails builder.Services.AddScoped<UserDetails>(); // 注册你的其他业务服务 builder.Services.AddScoped<IMyService, MyService>(); builder.Services.AddScoped<IMyGateway, MyGateway>(); var app = builder.Build(); // 注册用户信息中间件(需放在UseRouting、UseEndpoints之前) app.UseMiddleware<UserDetailsMiddleware>(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.Run();
4. 在业务服务中直接注入使用
由于UserDetails是Scoped实例,同一个请求内所有注入的UserDetails都是同一个对象,直接使用即可:
public class MyService : IMyService { private readonly IMyGateway _myGateway; private readonly UserDetails _userDetails; public MyService(IMyGateway myGateway, UserDetails userDetails) { _myGateway = myGateway; _userDetails = userDetails; } public async Task<string> MyMethod() { string userId = _userDetails.UserId.ToString(); // 此处可使用userId调用网关逻辑 return await _myGateway.GenerateAsync(); } }
关键说明
- Scoped生命周期:每个HTTP请求对应一个UserDetails实例,请求结束后自动销毁,既保证请求内复用,又避免多请求间的数据污染
- 中间件依赖注入:在InvokeAsync方法中直接注入UserDetails,ASP.NET Core会自动解析当前请求的Scoped实例
- 类型安全处理:解析UserId时用
int.TryParse避免非数字格式请求头引发的异常
内容的提问来源于stack exchange,提问作者WorksOnMyLocal
相关产品推荐
相关产品推荐

