2009-09-02 13 views

Respuesta

44

Ok, esto parece ser un comportamiento por diseño y un ejemplo perfecto de vexing exception. Esto se puede solucionar con esto:

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

Esto funciona en la mayoría de los casos, pero algunos servidores web pueden devolver un cuerpo de respuesta al devolver un error 404. ¡En ese caso, el código anterior trataría a un 404 como trata a un 304! – comshak

+0

@comshak eso es "bueno saberlo". El código de llamada deberá conocer cuáles son los códigos de respuesta aceptables. – roufamatic

+1

También agregué '|| ((HttpWebResponse) ex.Response) .StatusCode! = HttpStatusCode.NotModified' –

7

Esto es realmente un problema frustrante, y puede ser, alternativamente, trabajó en torno utilizando la siguiente clase de método de extensión y llamando 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; 
      } 
     } 
    } 
} 

Lees más sobre esto en mi blog sobre este tema en http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/

3

La manera de evitar esto es configurar System.WebException AllowAutoRedirect propiedad a false. Esto desactiva la lógica de redirección automática del WebRequest. Parece estar roto para 304 solicitudes de redireccionamiento, ya que no es una redirección real en el sentido más estricto. Por supuesto, eso significa que las otras solicitudes de redirección 3xx deben manejarse manualmente.

+1

Absolutamente brillante. ¿Por qué debería pagar la maquinaria excepcional de mano dura si no la necesito? – jsuddsjr

0

también me encontré con este problema con código:

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

y parece que si el servidor remoto devuelve 304 el estado que se debe pasar a Navegador lanzando este error o devolver a medida 304 para que el navegador podría volver respuesta en caché De lo contrario, probablemente recibirá respuesta vacía del servidor remoto.

Así que en mi caso de un comportamiento normal con el manejo de caché correcta Debe ser como:

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

Así como un FYI, esto es una actualización de Anton Gogolev's answer que utiliza el C# 6 (VS2015) when cláusula. Es un poco menos molesto cuando se utiliza un depurador, ya que elimina un punto de captura:

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