2009-09-02 17 views

risposta

44

Ok, questo sembra essere un comportamento di progettazione e un perfetto esempio di vexing exception. Questo può essere risolto con questo:

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

Questo funziona la maggior parte dei casi, ma alcuni server Web potrebbero restituire un corpo di risposta quando si restituisce un errore 404. In tal caso, il codice precedente tratterà un 404 poiché tratta un 304! – comshak

+0

@comshak è un "utile da sapere". Il codice chiamante dovrà essere consapevole di quali sono i codici di risposta accettabili. – roufamatic

+1

Ho anche aggiunto '|| ((HttpWebResponse) ex.Response) .StatusCode! = HttpStatusCode.NotModified' –

7

Questo è veramente un problema frustrante, e può essere alternativamente lavorato intorno utilizzando la seguente classe metodo di estensione e la chiamata 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; 
      } 
     } 
    } 
} 

Hai letto più su di esso nel mio post su questo argomento presso http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/

3

Il modo per evitare questo System.WebException è quello di impostare AllowAutoRedirect proprietà false. Disabilita la logica di reindirizzamento automatico di WebRequest. Sembra essere rotto per 304 richieste di reindirizzamento, in quanto non è un vero reindirizzamento nel senso più stretto. Ovviamente ciò significa che le altre richieste di reindirizzamento 3xx devono essere gestite manualmente.

+1

Assolutamente geniale. Perché dovrei pagare per il macchinario eccezionalmente pesante se non ne ho bisogno? – jsuddsjr

0

anche io sono imbattuto a questo problema con il codice:

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

e sembra che se server remoto restituisce 304 di stato che deve essere passato al browser Di gettando questo errore o di ritorno personalizzato 304 in modo che il browser potrebbe tornare risposta memorizzata nella cache. Altrimenti probabilmente riceverai una risposta vuota dal server remoto.

Quindi, nel mio caso, per un comportamento normale con la corretta gestione della cache dovrebbe essere come:

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

Proprio come un FYI, si tratta di un aggiornamento per Anton Gogolev's answer che utilizza la (VS2015) when clausola C# 6. È un po 'meno fastidioso quando si usa un debugger quando si rimuove uno slogan:

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