似乎AspNet.Core立即开始发送IEnumerable
的响应而不迭代整个集合。例如。:
[HttpGet("")]
public async Task<IActionResult> GetData()
{
IEnumerable<MyData> result = await _service.GetData();
return Ok(result.Select(_mapper.MapMyDataToMyDataWeb));
}
现在有一个异常发生在其中一个元素的映射过程中,所以我会假设一个500
响应,但实际上发生的是我得到一个只有部分(和不正确)Json的200
。
我认为这是一个功能,而不是Asp.Net Core
中的一个提供此行为的错误,并且通过调用例如它也可以相对容易地修复。 ToList()
,但我想知道是否有某种旗帜可以防止这种情况发生,因为它对于例如API项目和标准JSON响应。
我无法在描述此行为的文档中找到任何内容以及如何防止它。
附:我已经验证调用ToList()
修复了问题,响应为500且正确异常(使用UseDeveloperExceptionPage
)
看来这实际上是“按设计”,这个issue在Asp.Net Core github存储库中被提升了几次。
会发生的是,已经发送了带有200的标头,而不是正文。虽然我认为枚举必须在发送标题之前进行,但asp.net团队表示它将在服务器上使用更多资源,这就是为什么它就是这样。
这是一个引用:
在标题已经发送到客户端之后,很可能会在写入正文时抛出异常,因此在响应的一部分已经发送的200上没有回收。客户端将看到错误,因为正文将返回不完整。
如果你想确定性地报告500,当你发生这种情况时,你需要:
- 缓冲你的IEnumerable作为动作的一部分(.ToList())
- 缓冲响应体-https://github.com/aspnet/BasicMiddleware/tree/dev/src/Microsoft.AspNetCore.Buffering显然,这些都需要更多的服务器端资源,这就是为什么我们默认没有这种行为。
我可以确认这个解决方案有效:
Microsoft.AspNetCore.Buffering
包app.UseResponseBuffering()
之前写app.UseMvc()