2009-09-02 5 views

Antwort

44

Ok, das scheint ein By-Design-Verhalten und ein perfektes Beispiel für eine vexing exception. Dies kann mit dieser gelöst werden:

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

Dies funktioniert meisten Fällen, aber einige Web-Server könnte eine Antwort Körper zurück, wenn ein 404-Fehler zurück. In diesem Fall würde der obige Code ein 404 behandeln, wie es ein 304 behandelt! – comshak

+0

@comshak das ist ein "gut zu wissen." Der aufrufende Code muss sich dessen bewusst sein, was akzeptable Antwortcodes sind. – roufamatic

+1

Ich habe auch '|| hinzugefügt ((HttpWebResponse) ex.Response) .StatusCode! = HttpStatusCode.NotModified' –

7

Das ist wirklich ein frustrierendes Problem, und kann alternativ um unter Verwendung der folgenden Erweiterungsmethode Klasse und ruft 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; 
      } 
     } 
    } 
} 

Sie gearbeitet werden gelesen mehr darüber in meinem Blog-Post zu diesem Thema bei http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/

3

Die Art und Weise dieses System.WebException ist zu vermeiden AllowAutoRedirect Eigenschaft auf false einzustellen. Dies deaktiviert die automatische Umleitungslogik des WebRequest. Es scheint für 304 Redirection-Anfragen defekt zu sein, da es sich nicht um eine echte Umleitung im engeren Sinne handelt. Das bedeutet natürlich, dass die anderen Umleitungsanforderungen 3xx manuell bearbeitet werden müssen.

+1

Absolut brillant. Warum sollte ich für die schwerfällige Ausnahmemaschinerie bezahlen, wenn ich sie nicht brauche? – jsuddsjr

0

Ich kam auch in dieser Frage mit dem Code:

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

Und es scheint, dass, wenn der Remoteserver-304-Status zurückkehrt muss es durch das Werfen dieser Fehler oder Rückkehr benutzerdefinierten 304 so der Browser zu Browser weitergegeben werden konnte zurückkehren Cache-Antwort. Andernfalls erhalten Sie wahrscheinlich eine leere Antwort vom Remote-Server.

Also in meinem Fall für ein normales Verhalten mit der richtigen Cache sollte Umgang es sein:

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

Nur als FYI, dies ist ein Update für Anton Gogolev's answer, die die C# 6 (VS2015) when Klausel verwendet. Es ist ein wenig weniger ärgerlich, wenn ein Debugger wie es ein Catchpoint entfernt:

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