客户端已断开连接,因为基础请求已完成。不再有HttpContext可用

sas*_*alm 5 c# asp.net-web-api

我们间歇性地The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available在WebApi端点中遇到异常。

有谁知道导致此错误的原因,或者如何以一致的方式重现该错误?目前,它发生在100,000个请求中的150个中。

XmlDeserialize()在此部分代码中引发了异常:

[HttpPost]
public async Task<IHttpActionResult> Process()
{
    using (var requestStream = await Request.Content.ReadAsStreamAsync())
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyEntity));

        // !! The below line throws the exception
        MyEntity entity = serializer.Deserialize(requestStream) as MyEntity;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

这是完整的异常消息:

  "ExceptionType": "HttpException",
  "Message": "The client is disconnected because the underlying request has been completed.  There is no longer an HttpContext available.",
  "StackTrace": [
    "HttpBufferlessInputStream.Read;0",
    "SeekableBufferedRequestStream.Read;0",
    "XmlTextReaderImpl.ReadData;0",
    ...
Run Code Online (Sandbox Code Playgroud)

编辑:我在.NET的源代码中找到了这一点。 System.Web.txt

HttpBufferlessInputStream_ClientDisconnected=The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available.
Run Code Online (Sandbox Code Playgroud)

https://referencesource.microsoft.com/#system.web/HttpBufferlessInputStream.cs,332ecbede7a1f12a

// We are done if the count == 0 or there is no more content
while (count > 0 && _remainingBytes != 0) {
    // Do the actual read
    bytesRead = wr.ReadEntityBody(buffer, offset, count);
    if (bytesRead <= 0) {
        if (!_context.Response.IsClientConnected) {
            if (_persistEntityBody) {
                SetRawContentOnce();
            }
            throw new HttpException(SR.GetString(SR.HttpBufferlessInputStream_ClientDisconnected));
Run Code Online (Sandbox Code Playgroud)

因此,在wr.ReadEntityBody(buffer, offset, count)返回0或负数 之后,HttpBufferlessInputStream.Read()会引发异常,并且该异常_context.Response.IsClientConnected为false。

这意味着XmlDeserialize()仍在运行时,客户端已断开连接。但是根据我对netcat的有限实验,.NET一直等到整个XML请求都已上传,甚至没有调用controller方法。因此,我们仍在反序列化时不会上载请求。

Ora*_*ace 5

就像这里解释的那样您应该避免捕获同步上下文并使用.ConfigureAwait(false);

[HttpPost]
public async Task<IHttpActionResult> Process()
{
    using (var requestStream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyEntity));
        MyEntity entity = serializer.Deserialize(requestStream) as MyEntity;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

正如Thowk所注意到的,SynchronizationContext 已从 ASP.NET Core 中删除

  • 值得注意的是,SynchronizationContext 已从 ASP.NET Core 中删除。 (2认同)