.NET 8 Web API提交大集合遇SocketException问题求助
解决方案:解决.NET 8 Web API提交大列表时的SocketException错误
核心原因
该错误通常是请求体超出服务器/客户端大小限制或请求超时导致连接被强制关闭,1000条数据刚好处于阈值内,更大数据量则触发限制。
1. 调整ASP.NET Core服务器端的请求限制
在Blazor托管的Web API项目中,修改配置以允许更大的请求体:
方式一:全局配置(Program.cs)
// 调整Kestrel服务器的最大请求体大小 builder.Services.Configure<KestrelServerOptions>(options => { // 按需设置,例如100MB(单位:字节),或设为long.MaxValue允许无限制 options.Limits.MaxRequestBodySize = 100 * 1024 * 1024; }); // 若使用IIS托管,需额外配置表单限制 builder.Services.Configure<Microsoft.AspNetCore.Http.Features.FormOptions>(options => { options.MultipartBodyLengthLimit = 100 * 1024 * 1024; });
方式二:Action级别的局部配置
直接在API方法上标注限制:
[RequestSizeLimit(100 * 1024 * 1024)] // 100MB [HttpPost("ImportBranchAppointments/{ApiKey},{BranchCode}")] public async Task<ActionResult<int>> ImportBranchAppointmentsAsync(...) { // 原有逻辑 }
IIS部署额外配置(web.config)
如果Web API部署在IIS,需修改站点配置文件:
<system.webServer> <security> <requestFiltering> <!-- 100MB,单位字节 --> <requestLimits maxAllowedContentLength="104857600" /> </requestFiltering> </security> </system.webServer>
2. 优化WinForm客户端的请求配置
客户端的默认超时和序列化设置可能无法适配大数据传输:
// 初始化HttpClient时延长超时时间(例如5分钟) client.Timeout = TimeSpan.FromMinutes(5); // 优化JSON序列化,减少请求体体积 var jsonOptions = new JsonSerializerOptions { WriteIndented = false, // 关闭缩进减少冗余字符 IgnoreNullValues = true // 忽略空值字段 }; // 使用优化后的序列化选项发送请求 var Result = await client.PostAsJsonAsync( $"api/ImportData/ImportBranchAppointments/{ApiKey},{BranchCode}", Data, jsonOptions);
3. 改用流式传输(最优大对象方案)
如果数据量极大,流式传输可避免一次性将所有数据加载到内存,性能和稳定性更优:
服务器端修改
[HttpPost("ImportBranchAppointments/{ApiKey},{BranchCode}")] public async Task<ActionResult<int>> ImportBranchAppointmentsAsync( string ApiKey, string BranchCode, Stream requestStream) { var OrgGuid = ValidateApiKey(ApiKey); if (OrgGuid == "") { return Unauthorized("Invalid API key"); } try { int importedCount = 0; // 流式反序列化,逐行处理数据 await foreach (var appointment in JsonSerializer.DeserializeAsyncEnumerable<AppointmentModel>(requestStream)) { // 调用服务处理单个预约,或累积到一定批量后提交(如每100条一次) await _ImportService.ImportSingleAppointment(ApiKey, BranchCode, appointment); importedCount++; } return Ok(importedCount); } catch (Exception ex) { return StatusCode(500, $"Internal server error {ex.Message}"); } }
客户端修改
// 流式序列化并发送数据,避免内存过载 using var stream = new MemoryStream(); await JsonSerializer.SerializeAsync(stream, Data); stream.Position = 0; var content = new StreamContent(stream); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var Result = await client.PostAsync( $"api/ImportData/ImportBranchAppointments/{ApiKey},{BranchCode}", content);
4. 启用分块传输编码
客户端启用分块传输,避免一次性发送全部数据:
client.DefaultRequestHeaders.TransferEncodingChunked = true;
服务器端默认支持分块传输,无需额外配置。
方案优先级建议
- 先尝试调整请求大小限制+超时,实现成本最低,适合数据量不是极端大的场景;
- 若数据量持续增长,流式传输是最优方案,能大幅降低内存占用,避免超时问题;
- 分批提交作为备选方案,适合快速临时解决,但长期来看流式传输更高效。
内容的提问来源于stack exchange,提问作者Trevor
相关产品推荐
相关产品推荐

