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

如何捕获.NET Minimal API中无效JSON引发的BadHttpRequestException

.NET Minimal API 捕获JSON绑定类型不匹配的BadHttpRequestException

首先要明确:模型绑定(将JSON请求体反序列化为TransactionCreateDto)是在你的InsertTransaction方法执行前完成的,所以方法内部的try-catch根本捕获不到这个BadHttpRequestException。你可以用以下几种方式处理:

方法一:全局异常处理中间件

这是最通用的方案,能统一处理整个应用内的这类异常。在Program.cs中添加全局异常处理逻辑:

var builder = WebApplication.CreateBuilder(args);
// 注册你的服务(比如ITransactionRepository)
builder.Services.AddScoped<ITransactionRepository, TransactionRepository>();

var app = builder.Build();

// 全局异常处理中间件
app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        var exception = exceptionFeature?.Error;

        if (exception is BadHttpRequestException badRequestEx)
        {
            context.Response.StatusCode = StatusCodes.Status400BadRequest;
            context.Response.ContentType = "application/json";
            await context.Response.WriteAsJsonAsync(new
            {
                Message = "请求格式错误:字段类型不匹配",
                Details = badRequestEx.Message
            });
        }
        else
        {
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;
            await context.Response.WriteAsJsonAsync(new { Message = "服务器内部错误" });
        }
    });
});

// 其他中间件配置(比如授权、静态文件等)
// app.UseAuthorization();

app.MapPost("/transactions", TransactionsAPI.InsertTransaction);

app.Run();

方法二:端点级异常处理

如果只需要针对/transactions这个端点处理异常,可以在路由配置时添加过滤逻辑:

方式A:使用端点过滤器

app.MapPost("/transactions", TransactionsAPI.InsertTransaction)
   .AddEndpointFilter(async (context, next) =>
   {
       try
       {
           return await next(context);
       }
       catch (BadHttpRequestException badRequestEx)
       {
           return Results.BadRequest(new
           {
               Message = "请求体字段类型错误,请检查数据格式",
               Error = badRequestEx.Message
           });
       }
   });

方式B:简化版Handle方法

app.MapPost("/transactions", TransactionsAPI.InsertTransaction)
   .Handle<BadHttpRequestException>(ex =>
       Results.BadRequest(new 
       { 
           Message = "字段类型不匹配,请确保Price字段为数值类型", 
           Details = ex.Message 
       }));

方法三:手动反序列化(在Action内部捕获)

要是你希望把异常处理逻辑放在InsertTransaction方法里,可以放弃自动模型绑定,手动读取并反序列化请求体:

修改你的Action方法:

public static async Task<IResult> InsertTransaction(HttpRequest req, ITransactionRepository repo)
{
    try
    {
        var transactionDto = await req.ReadFromJsonAsync<TransactionCreateDto>();
        if (transactionDto == null)
        {
            return Results.BadRequest("请求体不能为空");
        }

        // 执行你的事务插入逻辑
        // await repo.InsertAsync(transactionDto);

        return Results.Ok("事务插入成功");
    }
    catch (JsonException jsonEx)
    {
        // 捕获反序列化失败的异常(比如Price传入字符串的情况)
        return Results.BadRequest(new
        {
            Message = "请求体格式错误:Price字段应为数值类型",
            Details = jsonEx.Message
        });
    }
    catch (Exception ex)
    {
        // 处理其他业务异常
        return Results.Problem(ex.Message);
    }
}

这种方式下,原来的BadHttpRequestException会被转化为JsonException(手动反序列化时抛出的异常类型),直接捕获即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:54:28