2009-09-02 7 views

Odpowiedz

44

OK, wydaje się, że jest to zachowanie towarzyszące projektowi i doskonałym przykładem modelu vexing exception. Problem ten można rozwiązać z tym:

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

Działa większości przypadków, ale niektóre serwery WWW może powrócić do ciała reakcji po powrocie błąd 404. W takim przypadku powyższy kod potraktuje 404, ponieważ traktuje 304! – comshak

+0

@comshak to "dobrze wiedzieć". Kod wywołujący musi być świadomy, jakie są dopuszczalne kody odpowiedzi. – roufamatic

+1

Dodałem także '|| ((HttpWebResponse) ex.Response) .StatusCode! = HttpStatusCode.NotModified' –

7

To jest naprawdę frustrujące problemu, a alternatywnie można obejść stosując następujące metody rozszerzenie klasy i nazywając 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; 
      } 
     } 
    } 
} 

czytasz więcej na ten temat na moim blogu na ten temat w http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/

3

sposobem na uniknięcie tego System.WebException jest ustawienie AllowAutoRedirect właściwość false. Powoduje wyłączenie automatycznej logiki przekierowania urządzenia WebRequest. Wygląda na to, że jest uszkodzony dla 304 żądań przekierowania, ponieważ nie jest prawdziwym przekierowaniem w ścisłym tego słowa znaczeniu. Oczywiście oznacza to, że inne żądania przekierowania muszą być obsługiwane ręcznie.

+1

Absolutnie genialny. Po co mam płacić za maszyny do obsługi wyjątków, jeśli ich nie potrzebuję? – jsuddsjr

0

doszedłem również w całej tej kwestii z kodem:

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

I wydaje się, że jeśli zdalny serwer zwraca 304 stan musi być przekazany do przeglądarki rzucając ten błąd lub powrocie zwyczaj 304 więc przeglądarka może wrócić buforowana odpowiedź. W przeciwnym razie prawdopodobnie otrzymasz pustą odpowiedź z serwera zdalnego.

Więc w moim przypadku do normalnego zachowania z prawidłową obsługę Cache powinno być tak:

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

tylko jako FYI, jest to aktualizacja do Anton Gogolev's answer że używa C# 6 (VS2015) when klauzuli. To trochę mniej irytujące, gdy za pomocą debuggera, gdyż usuwa jedną catchpoint:

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; 
    } 
} 
Powiązane problemy