ASP.NET Core Web API返回大JSON报404,DisableRequestSizeLimit不生效如何解决
你当前使用的[DisableRequestSizeLimit]和[RequestFormLimits]均用于限制入站请求的大小,和出站响应过大的故障完全无关,无法解决你的问题。可按以下优先级尝试解决方案:
- 修正路由配置
你当前接口的路由特性写为[HttpGet("id")],属于固定路由,仅能匹配路径/VpmGps/id,和你实际访问的/VpmGps/1并不匹配。小载荷请求可能是其他路由规则刚好命中,大载荷请求时逻辑超时触发路由 fallback 规则返回404。请将路由改为参数占位符形式:[HttpGet("{id}")] - 调整响应大小与缓冲区配置
.NET 5的ASP.NET Core默认限制了最大响应大小,大载荷序列化时还可能因为缓冲区溢出触发断连。在Startup.cs的ConfigureServices方法中添加如下配置:
也可以在接口方法内手动关闭当前请求的响应缓冲:services.Configure<MvcOptions>(options => { options.MaxHttpResponseSize = long.MaxValue; // 取消响应大小限制 });HttpContext.Response.DisableBuffering(); - 调整System.Text.Json序列化配置
默认JSON序列化器有最大深度限制,若你的VPMPoint类存在循环引用,大载荷序列化时会直接抛出异常触发断连。修改控制器注册配置:services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.MaxDepth = 128; // 按需调大,默认值为32 options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; // 忽略循环引用 options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; // 忽略空值减少载荷体积 }); - 调整Kestrel服务器限制
若你使用Kestrel作为托管服务器,默认配置了响应缓冲区大小和请求超时,大载荷序列化需要更长的处理时间。修改Program.cs的Kestrel配置:public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureKestrel(options => { options.Limits.MaxResponseBufferSize = null; // 取消响应缓冲区限制 options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5); // 调长连接保持时间 options.Limits.RequestTimeout = TimeSpan.FromMinutes(5); // 调长请求超时时间 }); webBuilder.UseStartup<Startup>(); }); - 调整IIS/IIS Express限制
若你使用IIS Express调试,需修改web.config配置放开响应大小和超时限制:<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="4294967295" /> <!-- 最大支持4GB响应 --> </requestFiltering> </security> <aspNetCore requestTimeout="00:05:00" /> </system.webServer> - 优化返回逻辑
一次性返回4万+JSON对象本身不符合API设计规范,你可以选择两种优化方案:- 分页返回:前端每次请求指定页码和每页条数,服务端分段返回数据
- 流式返回:将接口返回值改为
IAsyncEnumerable<VPMPoint>,边读取数据边序列化返回,无需将全量数据加载到内存,大幅降低序列化压力,示例代码:
[HttpGet("{id}")] public async IAsyncEnumerable<VPMPoint> Get(int id) { await foreach (var point in _dataService.GetVPMPointsAsAsyncEnumerable(id)) { yield return point; } } - 排查服务端异常
你当前的异常捕获逻辑仅打印控制台日志后重抛,若序列化过程中响应已经开始写入,异常会直接触发连接断开,浏览器会误报404。建议将异常日志持久化到文件,或附加调试器排查大载荷请求时是否抛出OutOfMemoryException、JsonException等异常。
内容的提问来源于stack exchange,提问作者Douglas Marquardt
相关产品推荐
相关产品推荐

