如何在ASP.NET中间件中捕获System.Text.Json序列化错误
解决ASP.NET Core JSON序列化异常捕获问题
你的try/catch块无法触发,核心原因是:Ok(apiEntity)仅创建了一个OkObjectResult对象,JSON序列化操作并非在Action方法执行时同步完成,而是后续ASP.NET Core管道的响应处理阶段才会执行,因此异常不会被当前Action内的catch捕获。
以下是几种可行的解决方案:
1. 自定义异常处理中间件
通过中间件捕获整个请求管道中发生的序列化异常,这是最通用的方式:
public class JsonSerializationExceptionMiddleware { private readonly RequestDelegate _next; private readonly ILogger<JsonSerializationExceptionMiddleware> _logger; public JsonSerializationExceptionMiddleware(RequestDelegate next, ILogger<JsonSerializationExceptionMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); } catch (ArgumentException ex) when (ex.Message.Contains("JSON value of length") && ex.Message.Contains("too large")) { _logger.LogError(ex, "JSON序列化遇到过大值错误"); context.Response.StatusCode = StatusCodes.Status400BadRequest; context.Response.ContentType = "application/json"; await context.Response.WriteAsJsonAsync(new ApiError { Message = "数据过大,无法完成序列化" }); } } }
注册中间件(在Program.cs中,需放在路由和端点中间件之前):
app.UseMiddleware<JsonSerializationExceptionMiddleware>(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
2. 使用Action结果过滤器
针对控制器Action的结果执行阶段捕获异常,更聚焦于API响应场景:
public class JsonSerializationFilter : IAsyncResultFilter { private readonly ILogger<JsonSerializationFilter> _logger; public JsonSerializationFilter(ILogger<JsonSerializationFilter> logger) { _logger = logger; } public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { try { await next(); } catch (ArgumentException ex) when (ex.Message.Contains("JSON value of length") && ex.Message.Contains("too large")) { _logger.LogError(ex, "JSON序列化过大值错误"); context.Result = new BadRequestObjectResult(new ApiError { Message = "数据超出序列化大小限制" }); } } }
注册过滤器(Program.cs中):
builder.Services.AddControllers(options => { options.Filters.Add<JsonSerializationFilter>(); });
3. 调整JSON序列化大小限制(可选)
如果业务允许返回超大对象,可以通过配置放宽序列化限制,从根源避免异常:
builder.Services.AddControllers() .AddJsonOptions(options => { // 调整JSON序列化的最大深度(默认64) options.JsonSerializerOptions.MaxDepth = 128; }); // 同时调整HTTP请求/响应的整体大小限制 builder.Services.Configure<Microsoft.AspNetCore.Http.Features.FormOptions>(options => { options.MultipartBodyLengthLimit = 800 * 1024 * 1024; // 示例:800MB });
额外建议
如果业务场景确实需要处理超大对象,优先考虑:
- 分页返回数据,避免一次性序列化全量数据
- 启用响应压缩(如Gzip),减少传输体积
- 使用流式响应,逐步序列化并返回数据
内容的提问来源于stack exchange,提问作者slastine
相关产品推荐
相关产品推荐

