[英]AspNet.Core returns 200 OK and invalid Json if there is an exception while iterating an IEnumerable (returned from controller)
It seems that AspNet.Core starts sending response that is IEnumerable
right away without iterating over the whole collection. 似乎AspNet.Core立即开始发送
IEnumerable
响应而不迭代整个集合。 Eg: 例如:
[HttpGet("")]
public async Task<IActionResult> GetData()
{
IEnumerable<MyData> result = await _service.GetData();
return Ok(result.Select(_mapper.MapMyDataToMyDataWeb));
}
Now there is an exception that happens during mapping of one of the elements, so I would assume a 500
response, but in reality what happens is that I get a 200
with only partial (and incorrect) Json. 现在在映射其中一个元素时会发生异常,因此我会假设
500
响应,但实际上发生的是我得到的200
只有部分(和不正确)的Json。
I assume it's a feature and not a bug in Asp.Net Core
that provides this behavior and it is additionally relatively easy to fix by calling eg ToList()
, but I am wondering if there is some kind of flag that can prevent this situation from happening since it does not really make sense for eg API project and standard JSON response. 我认为它是一个功能而不是
Asp.Net Core
一个提供此行为的错误,并且通过调用例如ToList()
还可以相对容易地修复,但我想知道是否存在某种可以防止这种情况的标志发生,因为它对于例如API项目和标准JSON响应没有意义。
I was not able to find anything in documentation that describes this behavior and how to prevent it. 我无法在描述此行为的文档中找到任何内容以及如何防止它。
PS I have verified that calling ToList()
fixes the issue and the response is 500 with correct exception (with UseDeveloperExceptionPage
) PS我已经验证调用
ToList()
修复了问题,响应为500且正确异常(使用UseDeveloperExceptionPage
)
It seems that this is actually "by design", this issue was raised few times on Asp.Net Core github repository. 看来这实际上是“按设计”,这个问题在Asp.Net Core github存储库中引发了几次。
What happens is that header with 200 is already sent, while the body is not. 会发生的是,已经发送了带有200的标头,而不是正文。 While I would think that enumeration must proceed before sending headers, asp.net team says it will use more resources on the server and that's why it is like that.
虽然我认为枚举必须在发送标题之前进行,但asp.net团队表示它将在服务器上使用更多资源,这就是为什么它就是这样。
Here is a quote: 这是一个引用:
It is very likely the case that your exception is thrown while writing to the body, after headers have already been sent to the client, so there's no take-backs on the 200 that was already sent as part of the response.
在标题已经发送到客户端之后,很可能会在写入正文时抛出异常,因此在响应的一部分已经发送的200上没有回收。 The client will see an error because the body will come back as incomplete.
客户端将看到错误,因为正文将返回不完整。
If you want to deterministically report a 500 when this happens you'll need to either:
如果你想确定性地报告500,当你发生这种情况时,你需要:
- Buffer your IEnumerable as part of the action (.ToList())
缓冲你的IEnumerable作为动作的一部分(.ToList())
- Buffer the response body - https://github.com/aspnet/BasicMiddleware/tree/dev/src/Microsoft.AspNetCore.Buffering Obviously both of these things require more server-side resources, which is why we don't have this kind of behavior by default.
缓冲响应主体 - https://github.com/aspnet/BasicMiddleware/tree/dev/src/Microsoft.AspNetCore.Buffering显然这两件事都需要更多的服务器端资源,这就是为什么我们没有这种默认情况下的行为。
I can confirm that this solution worked: 我可以确认这个解决方案有效:
Microsoft.AspNetCore.Buffering
package Microsoft.AspNetCore.Buffering
包 app.UseResponseBuffering()
before app.UseMvc()
app.UseResponseBuffering()
之前写app.UseMvc()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.