如何捕获.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
相关产品推荐
相关产品推荐

