ASP.NET Core 8中IExceptionHandler无法获取routeData问题求助
问题:ASP.NET Core 8中IExceptionHandler无法获取RouteData
问题概述
参考ASP.NET Core 8全局异常处理相关文章实现IExceptionHandler时,发现context.GetRouteData()始终返回null。即使移除了代码中重复的app.UseExceptionHandler("/Home/Error")调用,问题依然存在,但使用自定义异常中间件却能正常获取路由数据。
代码复现
GlobalExceptionHandler.cs
public class GlobalExceptionHandler : IExceptionHandler { private readonly ILogger<GlobalExceptionHandler> _logger; public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) { _logger = logger; } public async ValueTask<bool> TryHandleAsync( HttpContext context, Exception exception, CancellationToken cancellationToken) { // !!! routeData始终为null !!! var routeData = context.GetRouteData(); var controllerName = routeData?.Values["controller"]?.ToString(); var actionName = routeData?.Values["action"]?.ToString(); _logger.LogInformation("Controller={controller} Action={action}", controllerName, actionName); var response = new ProblemDetails() { Status = 500, Title = "Internal Server Error", Detail = "发生内部服务器错误,请联系MIS", Instance = context.Request.Path, }; await context.Response .WriteAsJsonAsync(response, cancellationToken); return true; } }
Program.cs
using ExceptionHandler01.Middlewares; var builder = WebApplication.CreateBuilder(args); // 添加服务到容器 builder.Services.AddControllersWithViews(); #region 注册GlobalExceptionHandler和ProblemDetails到DI builder.Services.AddExceptionHandler<GlobalExceptionHandler>(); builder.Services.AddProblemDetails(); #endregion var app = builder.Build(); // 配置HTTP请求管道 if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); // 默认HSTS值为30天,生产环境可根据需要调整 app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); //// 使用自定义异常中间件 //app.UseMiddleware<ExceptionHandlingMiddleware>(); // 使用默认异常处理 app.UseExceptionHandler(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
关键细节
- 需求是在异常发生时记录对应的控制器名称和动作名称
- 即使注释掉
app.UseExceptionHandler("/Home/Error"),IExceptionHandler中仍无法获取RouteData - 自定义
ExceptionHandlingMiddleware放在app.UseRouting()之后时,可正常获取RouteData
原因分析与解决方案
这并非Bug,而是IExceptionHandler的执行机制导致:
IExceptionHandler的执行时机在路由匹配之前,此时请求还未经过路由中间件处理,因此GetRouteData()返回null- 自定义中间件若放在
app.UseRouting()之后,能在路由匹配完成后捕获异常,自然可以获取到路由数据
解决方法
要在IExceptionHandler中获取路由数据,可手动触发路由匹配:
修改GlobalExceptionHandler.cs的TryHandleAsync方法:
using Microsoft.AspNetCore.Routing; // ... public async ValueTask<bool> TryHandleAsync( HttpContext context, Exception exception, CancellationToken cancellationToken) { // 手动执行路由匹配 var endpointRouteBuilder = context.RequestServices.GetRequiredService<IEndpointRouteBuilder>(); var router = endpointRouteBuilder.DefaultHandler; var routeContext = new RouteContext(context); await router.RouteAsync(routeContext); var routeData = routeContext.RouteData; var controllerName = routeData?.Values["controller"]?.ToString(); var actionName = routeData?.Values["action"]?.ToString(); _logger.LogInformation("Controller={controller} Action={action}", controllerName, actionName); // ... 其余响应逻辑不变 }
另外需注意:不要同时调用app.UseExceptionHandler("/Home/Error")和app.UseExceptionHandler(),二者会导致异常处理逻辑冲突,保留其中一个即可。
内容的提问来源于stack exchange,提问作者jasper
相关产品推荐
相关产品推荐

