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

ASP.NET Core MVC全局异常处理中间件无法跳转自定义错误页如何解决?

问题根因

  • 你在修改请求路径前已经向响应流写入了JSON内容、设置了application/json的响应类型,响应头已部分发送,后续修改请求路径的操作不会生效
  • 修改Request.Path后没有重新触发中间件管道执行新的路径匹配逻辑,不会自动路由到你配置的错误页接口/Action

方案1:调整现有自定义中间件逻辑

你需要调整执行顺序,区分API请求和页面请求,修改路径后重新触发管道即可:

public class ErrorHandlerMiddleware
{
    private readonly RequestDelegate _next;

    public ErrorHandlerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // 避免错误页本身抛出异常导致无限循环
        if (context.Request.Path.StartsWithSegments("/error"))
        {
            await _next(context);
            return;
        }

        try
        {
            await _next(context);
        }
        catch (Exception error)
        {
            var response = context.Response;
            // 先清除已经写入的响应内容和响应头
            response.Clear();
            
            // 根据异常类型设置状态码
            switch (error)
            {
                case KeyNotFoundException e:
                    response.StatusCode = (int)HttpStatusCode.NotFound;
                    break;
                default:
                    response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    break;
            }

            // 区分API请求和页面请求:如果是请求API接口返回JSON,否则跳转错误页
            if (context.Request.ContentType == "application/json" || context.Request.Path.StartsWithSegments("/api"))
            {
                response.ContentType = "application/json";
                var result = JsonSerializer.Serialize(new { message = error?.Message });
                await response.WriteAsync(result);
            }
            else
            {
                // 修改请求路径,重新触发管道执行,路由到错误页
                context.Request.Path = $"/error/{response.StatusCode}";
                await _next(context);
            }
        }
    }
}

注意:需要在Program.cs中把这个中间件注册到所有中间件的最开头,才能捕获全管道的异常。

方案2:使用ASP.NET Core内置错误处理组件(更推荐)

不用自行实现中间件,官方提供的组件已经覆盖了全局异常、状态码错误处理的需求,符合ASP.NET Core设计规范:

Program.cs配置

var builder = WebApplication.CreateBuilder(args);

// 添加控制器和视图服务(MVC)
builder.Services.AddControllersWithViews();

var app = builder.Build();

// 开发环境使用开发者异常页,生产环境使用自定义错误页
if (!app.Environment.IsDevelopment())
{
    // 全局异常处理
    app.UseExceptionHandler("/error/500");
    // 处理404等非异常类的状态码错误
    app.UseStatusCodePagesWithReExecute("/error/{0}");
}
else
{
    app.UseDeveloperExceptionPage();
}

app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

ErrorController示例

public class ErrorController : Controller
{
    [Route("/error/{code:int}")]
    public IActionResult Error(int code)
    {
        // 根据不同状态码返回对应错误页,也可以统一返回通用错误页
        return code switch
        {
            404 => View("NotFound"),
            500 => View("InternalError"),
            _ => View("CommonError", code)
        };
    }
}

你只需要在Views/Error文件夹下创建对应的错误页视图即可,该方案同时覆盖了异常捕获、404等无异常的错误状态码处理场景。

内容的提问来源于stack exchange,提问作者Pilouni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:06:00