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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 15:07:31