Подтвердить что ты не робот

HttpWebRequest.GetResponse выдает WebException по HTTP 304

Когда веб-сервер отвечает на HttpWebRequest.GetResponse() с помощью HTTP 304 (Not Modified), GetResponse() показывает WebException, что для меня очень странно. Является ли это по дизайну или мне не хватает чего-то очевидного здесь?

4b9b3361

Ответ 1

Хорошо, это похоже на поведенческое поведение и прекрасный пример досадного исключения. Это можно решить следующим образом:

public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
    try
    {
        return (HttpWebResponse) request.GetResponse();
    }
    catch (WebException ex)
    {
        if(ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)
            throw; 

        return (HttpWebResponse)ex.Response;
    }
}

Ответ 2

Это действительно неприятная проблема, и ее можно альтернативно обойти, используя следующий класс метода расширения и вызывающий запрос .BetterGetResponse()

//-----------------------------------------------------------------------
//
//     Copyright (c) 2011 Garrett Serack. All rights reserved.
//
//
//     The software is licensed under the Apache 2.0 License (the "License")
//     You may not use the software except in compliance with the License.
//
//-----------------------------------------------------------------------

namespace CoApp.Toolkit.Extensions {
    using System;
    using System.Net;

    public static class WebRequestExtensions {
        public static WebResponse BetterEndGetResponse(this WebRequest request, IAsyncResult asyncResult) {
            try {
                return request.EndGetResponse(asyncResult);
            }
            catch (WebException wex) {
                if( wex.Response != null ) {
                    return wex.Response;
                }
                throw;
            }
        }

        public static WebResponse BetterGetResponse(this WebRequest request) {
            try {
                return request.GetResponse();
            }
            catch (WebException wex) {
                if( wex.Response != null ) {
                    return wex.Response;
                }
                throw;
            }
        }
    }
}

Подробнее об этом читайте в своем сообщении в блоге на эту тему http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/

Ответ 3

Способ избежать этого System.WebException - установить AllowAutoRedirect свойство false. Это отключает логику автоматического перенаправления WebRequest. Кажется, что он был нарушен для 304 запросов перенаправления, поскольку он не является реальным перенаправлением в строгом смысле. Конечно, это означает, что другие запросы перенаправления 3xx должны обрабатываться вручную.

Ответ 4

Так же, как FYI, это обновление для ответа Антона Гоголева, в котором используется предложение С# 6 (VS2015) when. Это немного менее раздражает при использовании отладчика, поскольку он удаляет одну точку останова:

public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
    try
    {
        return (HttpWebResponse) request.GetResponse();
    }
    catch (WebException ex)
        when (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
    {
        return (HttpWebResponse) ex.Response;
    }
}

Ответ 5

Я также столкнулся с этой проблемой с кодом:

try
{
    ...
    var webResponse = req.GetResponse();
    ...
}
catch (WebException ex)
{
    Log.Error("Unknown error occured", ex);
    //throw; 
}

И похоже, что если Remote Server возвращает статус 304, он должен быть передан в браузер, путем выброса этой ошибки или возврата пользовательского 304, чтобы браузер мог возвращать кешированный ответ. В противном случае вы, вероятно, получите пустой ответ от удаленного сервера.

Итак, в моем случае для нормального поведения с правильной обработкой кэша он должен выглядеть следующим образом:

try
{
    ...
    var webResponse = req.GetResponse();
    ...
}
catch (WebException ex)
{
    if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotModified)
        throw;
    Log.Error("Unknown error occured", ex);
}