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

ASP.NET Core 8.0 Web API全局异常处理统一响应方案问询

ASP.NET Core 8.0 Web API全局统一异常处理方案

问题背景

我正在构建ASP.NET Core 8.0 Web API,需要实现全局异常处理,确保应用中任何位置的异常都返回一致格式的JSON响应。当前不同错误场景的响应格式不一致:

  • 自定义业务逻辑异常返回:
{
  "message": "User not found"
}
  • 模型验证错误返回:
{
  "errors": {
    "Email": ["Email is required"]
  }
}
  • 未处理异常(500错误)在生产环境仅返回通用错误页或空响应。

期望的统一响应格式

所有错误都需要返回如下结构的JSON:

{
  "statusCode": 404,
  "message": "User not found",
  "details": "Additional context here"
}

已尝试的方案及问题

  1. 自定义异常中间件
    代码实现:
public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = StatusCodes.Status500InternalServerError;

        var response = new
        {
            statusCode = context.Response.StatusCode,
            message = exception.Message
        };

        return context.Response.WriteAsJsonAsync(response);
    }
}

注册方式:

app.UseMiddleware<ExceptionMiddleware>();

问题:仅能捕获未处理异常,无法处理模型绑定验证错误或过滤器中抛出的异常。

  1. 内置UseExceptionHandler
    代码实现:
app.UseExceptionHandler("/error");

app.Map("/error", (HttpContext context) =>
{
    var exception = context.Features.Get<IExceptionHandlerFeature>()?.Error;
    return Results.Problem(title: exception?.Message);
});

问题:返回默认ProblemDetails格式,不符合自定义需求,且无法捕获验证错误。


解决方案

1. 捕获所有错误的推荐方案

在ASP.NET Core 8.0 Web API中,要覆盖未处理异常、验证错误、自定义异常所有场景,需要组合两种核心方式:

  • 自定义异常中间件(处理管道中绝大多数同步/异步未捕获异常)
  • 配置ApiBehaviorOptions(替换默认的模型验证错误响应格式)

2. 中间件、过滤器还是UseExceptionHandler?

  • 中间件:优先级最高,能捕获路由匹配、过滤器、Action执行等全管道环节的异常,是全局异常处理的核心载体。
  • 异常过滤器:仅能捕获Action执行过程(含模型绑定后、ActionFilter内)的异常,无法覆盖路由、中间件层级的错误,仅适合作为补充场景使用。
  • UseExceptionHandler:内置方案但定制化能力弱,默认返回ProblemDetails格式,不适合需要完全自定义响应结构的场景。

综上,推荐以自定义中间件为主,配合ApiBehaviorOptions处理验证错误。

3. 统一验证错误的响应格式

通过配置ApiBehaviorOptions替换默认的验证错误生成逻辑:

builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = context =>
    {
        // 收集所有验证错误并拼接为详情文本
        var errorDetails = string.Join("; ", 
            context.ModelState
                .Where(e => e.Value.Errors.Any())
                .SelectMany(kv => kv.Value.Errors.Select(err => err.ErrorMessage))
        );

        var response = new
        {
            statusCode = StatusCodes.Status400BadRequest,
            message = "Validation failed",
            details = errorDetails
        };

        return new BadRequestObjectResult(response);
    };
});

4. 区分不同异常类型返回对应状态码

先定义业务相关的自定义异常(示例):

public class NotFoundException : Exception
{
    public NotFoundException(string message) : base(message) { }
}

public class ValidationException : Exception
{
    public ValidationException(string message) : base(message) { }
}

然后扩展中间件的异常处理逻辑,根据异常类型映射HTTP状态码:

private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
    context.Response.ContentType = "application/json";
    
    // 根据异常类型匹配响应信息
    var errorInfo = exception switch
    {
        NotFoundException notFoundEx => (
            StatusCode: StatusCodes.Status404NotFound,
            Message: notFoundEx.Message,
            Details: "Requested resource does not exist"
        ),
        ValidationException validationEx => (
            StatusCode: StatusCodes.Status400BadRequest,
            Message: validationEx.Message,
            Details: "Input data validation failed"
        ),
        _ => (
            StatusCode: StatusCodes.Status500InternalServerError,
            Message: "An unexpected error occurred",
            Details: 
#if DEBUG
                exception.ToString() // 开发环境返回完整异常栈
#else
                "Internal server error" // 生产环境隐藏敏感信息
#endif
        )
    };

    context.Response.StatusCode = errorInfo.StatusCode;

    var response = new
    {
        statusCode = errorInfo.StatusCode,
        message = errorInfo.Message,
        details = errorInfo.Details
    };

    return context.Response.WriteAsJsonAsync(response);
}

最终Program.cs配置示例

注意中间件注册顺序:需放在UseRouting()之后、UseAuthorization()之前:

var builder = WebApplication.CreateBuilder(args);

// 添加控制器服务
builder.Services.AddControllers();

// 配置验证错误响应格式
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = context =>
    {
        var errorDetails = string.Join("; ", 
            context.ModelState
                .Where(e => e.Value.Errors.Any())
                .SelectMany(kv => kv.Value.Errors.Select(err => err.ErrorMessage))
        );

        var response = new
        {
            statusCode = StatusCodes.Status400BadRequest,
            message = "Validation failed",
            details = errorDetails
        };

        return new BadRequestObjectResult(response);
    };
});

var app = builder.Build();

// 注册自定义异常中间件
app.UseMiddleware<ExceptionMiddleware>();

app.UseAuthorization();

app.MapControllers();

app.Run();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 19:34:51