2009-09-02 5 views

ответ

44

Хорошо, это похоже на поведенческое поведение и прекрасный пример vexing exception. Это может быть решена с этим:

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; 
    } 
} 
+3

Это работает в большинстве случаев, но некоторые веб-серверы могут вернуть тело ответа при возврате ошибки 404. В этом случае код выше будет обрабатывать 404, поскольку он обрабатывает 304! – comshak

+0

@comshak это «хорошо знать». Вызывающий код должен знать о допустимых кодах ответа. – roufamatic

+1

Я также добавил '|| ((HttpWebResponse) ex.Response) .StatusCode! = HttpStatusCode.NotModified' –

7

Это действительно расстраивает проблема, и в качестве альтернативы можно обойти, используя следующий класс метод расширения и вызова request.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 должны обрабатываться вручную.

+1

Абсолютно блестящий. Почему я должен платить за тяжелое оборудование для исключения, если оно мне не нужно? – jsuddsjr

0

я наткнулся на этот вопрос с кодом:

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

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

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

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

Подобно тому, как FYI, это обновление Anton Gogolev's answer, который использует (VS2015) when положения на C# 6. Это немного менее раздражает при использовании отладчика, поскольку он удаляет одну точку останова:

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; 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^