HttpClient.SendAsync HttpException: клиент отключен

У меня есть приложение веб-API ASP.NET, размещенное в веб-роли Windows Azure. Целью этого приложения является прокси-запросы Http к другим конечным точкам с поддержкой Интернета, таким как ретранслятор служебной шины, и возврат их ответа.

Иногда наше приложение выдает исключение при отправке запроса со значительной полезной нагрузкой (> 5 МБ). Это может произойти в 1 из 20 запросов с большой полезной нагрузкой.

Сведения об исключении: System.AggregateException: произошла одна или несколько ошибок. ---> System.Web.HttpException: клиент отключен.
в System.Web.Hosting.IIS7WorkerRequest.EndRead(IAsyncResult asyncResult) в System.Web.HttpBufferlessInputStream.EndRead(IAsyncResult asyncResult) в System.Net.Http. StreamToStreamCopy.BufferReadCallback(IAsyncResult ar) --- Конец трассировки стека внутреннего исключения --- ---> (Внутреннее исключение №0) System.Web.HttpException (0x800703E3): клиент отключен. в System.Web.Hosting.IIS7WorkerRequest.EndRead(IAsyncResult asyncResult) в System.Web.HttpBufferlessInputStream.EndRead(IAsyncResult asyncResult) в System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar)‹--- ; Событие TraceSource 'w3wp.exe'

Мы отправляем эти Http-запросы с помощью System.Net.HttpClient в .NET 4.5.

public class ProxyController : ApiController
{
    private static readonly HttpClient HttpClient = new HttpClient();
    private static readonly Uri BaseUri = new Uri("http://webendpoint.com");

    public HttpResponseMessage Post()
    {
        var newUri = new Uri(BaseUri, Request.RequestUri.PathAndQuery);
        var request = new HttpRequestMessage(HttpMethod.Post, newUri)
                {
                    Content = this.Request.Content
                };

        var task = HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
        task.Wait();
        var response = task.Result;
        return new HttpResponseMessage(response.StatusCode)
        {
            Content = new PushStreamContent((stream, content, ctx) =>
            {
                var tempStream = response.Content.ReadAsStreamAsync().Result;
                tempStream.CopyToAsync(stream).Wait();
                stream.Flush();
                stream.Close();
            })
        };
    }
}

Любые мысли о том, что может быть причиной этой проблемы?


person Gavin Osborn    schedule 23.05.2013    source источник
comment
Трудно помочь вам отладить этот код, так как вы, должно быть, написали его по памяти, потому что он полон ошибок. Однако первое, что я бы порекомендовал, если вы действительно создаете только прокси, — это просто использовать DelegatingHandler и не заморачиваться с ApiController.   -  person Darrel Miller    schedule 23.05.2013
comment
Справедливое замечание, я не делал тебе никаких одолжений этим кодом. Моя вина. Обновлено.   -  person Gavin Osborn    schedule 24.05.2013


Ответы (1)


Попробуйте вернуть версию задачи, а затем замените код синхронизации на асинхронный. Больше никаких «.Results», вместо этого используйте ключевое слово «await» и поместите ключевое слово «asyc» в свой метод. Что-то вроде этого:

public class ProxyController : ApiController
{
    private static readonly HttpClient HttpClient = new HttpClient();
    private static readonly Uri BaseUri = new Uri("http://webendpoint.com");

    public async Task<HttpResponseMessage> Post()
    {
        var newUri = new Uri(BaseUri, Request.RequestUri.PathAndQuery);
        var request = new HttpRequestMessage(HttpMethod.Post, newUri)
        {
            Content = Request.Content
        };

        var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

        return new HttpResponseMessage(response.StatusCode)
        {
            Content = new PushStreamContent(async (stream, content, ctx) =>
            {
                var tempStream = await response.Content.ReadAsStreamAsync();
                await tempStream.CopyToAsync(stream);
                stream.Flush();
                stream.Close();
            })
        };
    }
}
person Paul Fryer    schedule 05.11.2014