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

.NET 7最小API:IExceptionFilter注册及全局异常处理问题

最小API全局异常处理解决方案

最小API不像MVC控制器体系那样支持IExceptionFilter注册,下面提供三种实用方案解决你的问题:


方案一:自定义全局异常中间件(推荐)

这是最灵活且不受环境限制的方式,能捕获所有请求的异常,调试/生产模式均生效。

1. 编写异常处理中间件

public class GlobalExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<GlobalExceptionMiddleware> _logger;

    public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "未处理的全局异常");
            await HandleExceptionResponse(context, ex);
        }
    }

    private static async Task HandleExceptionResponse(HttpContext context, Exception ex)
    {
        context.Response.ContentType = "application/json";
        // 根据异常类型自定义状态码
        context.Response.StatusCode = ex switch
        {
            ArgumentException => StatusCodes.Status400BadRequest,
            KeyNotFoundException => StatusCodes.Status404NotFound,
            _ => StatusCodes.Status500InternalServerError
        };

        // 构造自定义响应体,调试模式可返回详细信息,生产模式可隐藏
        var response = new
        {
            StatusCode = context.Response.StatusCode,
            Message = context.Response.StatusCode == 500 ? "服务器内部错误" : ex.Message,
            DebugDetail = Environment.IsDevelopment() ? ex.ToString() : null
        };

        await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(response));
    }
}

2. 注册中间件到管道

在Program.cs中,确保中间件放在管道最靠前的位置(早于路由、端点注册):

var builder = WebApplication.CreateBuilder(args);

// 注册服务...

var app = builder.Build();

// 注册全局异常中间件
app.UseMiddleware<GlobalExceptionMiddleware>();

app.UseRouting();

// 其他中间件、路由注册...
app.MapGet("/api/test", () =>
{
    throw new InvalidOperationException("仓储层测试异常");
});

app.Run();

方案二:改造UseExceptionHandler使其调试模式生效

默认UseExceptionHandler在开发模式下会被开发者异常页面覆盖,只需禁用开发者异常页面即可让它接管所有环境的异常处理:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// 注释或移除开发者异常页面,让UseExceptionHandler生效
// app.UseDeveloperExceptionPage();

app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        context.Response.ContentType = "application/json";
        var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        var ex = exceptionFeature?.Error;

        context.Response.StatusCode = ex != null ? StatusCodes.Status500InternalServerError : StatusCodes.Status404NotFound;

        var response = new
        {
            Path = exceptionFeature?.Path,
            Message = ex?.Message ?? "请求路径不存在",
            StatusCode = context.Response.StatusCode
        };

        await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(response));
    });
});

// 路由、端点注册...
app.MapGet("/api/test", () =>
{
    throw new Exception("仓储层抛出异常");
});

app.Run();

方案三:端点过滤器(针对单个/批量端点)

如果只需处理特定端点的异常,可使用端点过滤器:

单个端点添加过滤器

app.MapGet("/api/test", () =>
{
    throw new InvalidOperationException("测试异常");
})
.AddEndpointFilter(async (context, next) =>
{
    try
    {
        return await next(context);
    }
    catch (Exception ex)
    {
        return Results.Json(new { Message = ex.Message }, statusCode: 500);
    }
});

全局注册端点过滤器

对所有最小API端点生效:

builder.Services.Configure<RouteHandlerOptions>(options =>
{
    options.AddEndpointFilter(async (context, next) =>
    {
        try
        {
            return await next(context);
        }
        catch (Exception ex)
        {
            return Results.Json(new 
            { 
                StatusCode = 500, 
                Message = "服务器处理失败",
                Detail = Environment.IsDevelopment() ? ex.Message : null
            });
        }
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:52:48