.NET 6中间件通过HttpContext获取Controller名称返回null的解决方法
.NET 6 中间件获取Controller名称解决方案
根因分析
你遇到的RouteValues["controller"]返回null的核心原因是中间件注册顺序错误:
在.NET 6的WebApplication管道模型中,路由匹配逻辑(负责填充RouteValues、解析端点信息)会在隐式注入的UseRouting中间件执行时完成,而你将UseAuditLogMiddleware注册在了MapControllers之后,中间件执行时路由匹配还未完成,自然拿不到控制器信息。
解决方案
第一步:调整中间件注册顺序
修改Program.cs中的中间件注册顺序,将自定义审计日志、错误日志中间件放到MapControllers之前,调整后代码如下:
// 原有其他配置保持不变 app.UseHttpsRedirection(); app.UseAuthorization(); app.UseElmah(); // 把自定义中间件移到MapControllers之前 app.UseAuditLogMiddleware(); app.UseErrorLoggingMiddleware(); app.MapControllers(); // 端点注册放在自定义中间件之后 app.Run();
第二步:使用稳定的取值方式
调整顺序后可以继续用RouteValues取值,也可以直接从端点元数据中获取ControllerActionDescriptor来拿控制器名称,兼容性更强,不会受自定义路由规则影响:
// 需先引用命名空间 Microsoft.AspNetCore.Mvc.Controllers public async Task Invoke(HttpContext httpContext, IUserContext userContext, IAuditLogContract auditLogContract) { // 方式1:RouteValues取值(顺序调整后可用) var controllerName1 = httpContext.Request.RouteValues["controller"]?.ToString(); // 方式2:从端点元数据取值(更稳定) var controllerActionDescriptor = httpContext.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>(); var controllerName2 = controllerActionDescriptor?.ControllerName; auditLogContract.Add(new AuditLog { LoginStatus = !string.IsNullOrEmpty(userContext.Id), Controller = controllerName2 ?? controllerName1, // 其余代码保持不变 }); await this.next(httpContext); }
注:如果请求命中的是静态文件、Swagger等非Controller端点,拿不到Controller名称属于正常情况,空值判断即可正常兼容。
内容的提问来源于stack exchange,提问作者Amol Borkar
相关产品推荐
相关产品推荐

