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

ASP.NET Core 8.0 Web API:如何用IExceptionHandler处理400与404错误?

解决ASP.NET Core 8 Web API中400/404异常处理及调试问题

一、修正异常处理器配置问题

你当前的Program.cs配置存在冲突:app.UseExceptionHandler("/Error")是传统异常页面的用法,会覆盖你注册的GlobalExceptionHandler,导致无法进入调试。同时配置顺序也需要调整,确保异常处理器在管道早期执行。

修正后的Program.cs核心配置:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 注册自定义异常处理器
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
// 配置ProblemDetails,统一处理框架生成的状态码(如400、404)
builder.Services.AddProblemDetails(options =>
{
    options.CustomizeProblemDetails = ctx =>
    {
        // 自定义404响应
        if (ctx.ProblemDetails.Status == StatusCodes.Status404NotFound)
        {
            ctx.ProblemDetails.Title = "资源未找到";
            ctx.ProblemDetails.Detail = "请求的端点或资源不存在";
        }
        // 自定义400响应(含模型验证错误)
        else if (ctx.ProblemDetails.Status == StatusCodes.Status400BadRequest)
        {
            ctx.ProblemDetails.Title = "无效请求";
            var modelState = ctx.HttpContext.Features.Get<ModelStateFeature>()?.ModelState;
            if (modelState != null && modelState.Any(e => e.Value.Errors.Any()))
            {
                ctx.ProblemDetails.Detail = string.Join("; ", 
                    modelState.SelectMany(e => e.Value.Errors.Select(err => err.ErrorMessage)));
            }
        }
    };
});

var app = builder.Build();

// 启用自定义异常处理器(不要指定/Error路径)
app.UseExceptionHandler();
// 启用状态码页面中间件,捕获404等非异常类状态码
app.UseStatusCodePages();

// 开发环境配置
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// 路由、授权等中间件(按需添加)
app.UseRouting();
app.UseAuthorization();

app.MapControllers(); // 控制器API需添加此配置

app.Run();

二、优化全局异常处理器

默认的GlobalExceptionHandler只处理500错误,可扩展为根据异常类型返回对应状态码,同时在开发环境返回堆栈信息便于调试:

public class GlobalExceptionHandler : IExceptionHandler
{
    private readonly ILogger<GlobalExceptionHandler> _logger;
    private readonly IWebHostEnvironment _env;

    public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger, IWebHostEnvironment env)
    {
        _logger = logger;
        _env = env;
    }

    public async ValueTask<bool> TryHandleAsync(
        HttpContext httpContext,
        Exception exception,
        CancellationToken cancellationToken)
    {
        _logger.LogError(exception, "异常发生: {Message}", exception.Message);

        var problemDetails = new ProblemDetails();

        // 根据异常类型匹配状态码
        switch (exception)
        {
            case ValidationException validationEx:
                problemDetails.Status = StatusCodes.Status400BadRequest;
                problemDetails.Title = "验证失败";
                problemDetails.Detail = string.Join("; ", validationEx.Errors.Select(e => e.ErrorMessage));
                break;
            case FileNotFoundException fileNotFoundEx:
                problemDetails.Status = StatusCodes.Status404NotFound;
                problemDetails.Title = "文件未找到";
                problemDetails.Detail = fileNotFoundEx.Message;
                break;
            default:
                problemDetails.Status = StatusCodes.Status500InternalServerError;
                problemDetails.Title = "服务器错误";
                // 开发环境返回完整异常信息,生产环境隐藏
                problemDetails.Detail = _env.IsDevelopment() ? exception.ToString() : "内部服务器错误";
                break;
        }

        httpContext.Response.StatusCode = problemDetails.Status.Value;
        await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);

        return true;
    }
}

三、为什么400错误没进入异常处理器?

当你未传递fileName查询参数时,ASP.NET Core的模型验证在到达你的端点之前就已失败,框架会自动生成400响应,默认不会将此异常抛给IExceptionHandler。通过上述AddProblemDetails的配置,就能统一自定义这类框架生成的状态码响应。

四、结论

不需要单独编写两个自定义中间件,通过以下步骤即可统一处理所有异常和状态码:

  1. 移除冲突的app.UseExceptionHandler("/Error"),改用app.UseExceptionHandler()启用自定义处理器;
  2. 配置AddProblemDetails自定义400、404等框架生成的状态码响应;
  3. 启用UseStatusCodePages捕获非异常类状态码;
  4. 扩展GlobalExceptionHandler处理业务异常并返回对应状态码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:10:59