Pregunta .Net HttpWebRequest.GetResponse () provoca una excepción cuando se devuelve el código de estado HTTP 400 (solicitud incorrecta)


Estoy en una situación en la que cuando obtengo un código HTTP 400 del servidor, es una forma completamente legal de que el servidor me diga cuál fue el problema con mi solicitud (usando un mensaje en el contenido de respuesta HTTP)

Sin embargo, .NET HttpWebRequest genera una excepción cuando el código de estado es 400.

¿Cómo manejo esto? Para mí, un 400 es completamente legal y bastante útil. El contenido HTTP tiene información importante, pero la excepción me saca de mi camino.


183
2018-03-28 06:40


origen


Respuestas:


Sería bueno si hubiera alguna forma de desactivar el "código de lanzamiento sin éxito", pero si capturas WebException puedes al menos usar la respuesta:

using System;
using System.IO;
using System.Web;
using System.Net;

public class Test
{
    static void Main()
    {
        WebRequest request = WebRequest.Create("http://csharpindepth.com/asd");
        try
        {
            using (WebResponse response = request.GetResponse())
            {
                Console.WriteLine("Won't get here");
            }
        }
        catch (WebException e)
        {
            using (WebResponse response = e.Response)
            {
                HttpWebResponse httpResponse = (HttpWebResponse) response;
                Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    string text = reader.ReadToEnd();
                    Console.WriteLine(text);
                }
            }
        }
    }
}

Es posible que desee encapsular el bit "obtener una respuesta incluso si no es un código de éxito" en un método diferente. (Sugeriría que aún arrojes si no hay una respuesta, por ejemplo, si no pudiste conectarte).

Si la respuesta de error puede ser grande (lo cual es inusual) es posible que desee ajustar HttpWebRequest.DefaultMaximumErrorResponseLength para asegurarse de obtener el error completo.


308
2018-03-28 07:07



Sé que esto ya se ha respondido hace mucho tiempo, pero hice un método de extensión para ayudar a otras personas que llegan a esta pregunta.

Código:

public static class WebRequestExtensions
{
    public static WebResponse GetResponseWithoutException(this WebRequest request)
    {
        if (request == null)
        {
            throw new ArgumentNullException("request");
        }

        try
        {
            return request.GetResponse();
        }
        catch (WebException e)
        {
            if (e.Response == null)
            {
                throw;
            }

            return e.Response;
        }
    }
}

Uso:

var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com");

//... (initialize more fields)

using (var response = (HttpWebResponse)request.GetResponseWithoutException())
{
    Console.WriteLine("I got Http Status Code: {0}", response.StatusCode);
}

42
2018-01-17 17:56



Tuve problemas similares al intentar conectarme al servicio OAuth2 de Google.

Terminé escribiendo el POST manualmente, no usando WebRequest, así:

TcpClient client = new TcpClient("accounts.google.com", 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient("accounts.google.com");

{
    byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToString());

    StringBuilder msg = new StringBuilder();
    msg.AppendLine("POST /o/oauth2/token HTTP/1.1");
    msg.AppendLine("Host: accounts.google.com");
    msg.AppendLine("Content-Type: application/x-www-form-urlencoded");
    msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToString());
    msg.AppendLine("");
    Debug.WriteLine("Request");
    Debug.WriteLine(msg.ToString());
    Debug.WriteLine(content.ToString());

    byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
    sslStream.Write(headerAsBytes);
    sslStream.Write(contentAsBytes);
}

Debug.WriteLine("Response");

StreamReader reader = new StreamReader(sslStream);
while (true)
{  // Print the response line by line to the debug stream for inspection.
    string line = reader.ReadLine();
    if (line == null) break;
    Debug.WriteLine(line);
}

La respuesta que se escribe en la secuencia de respuesta contiene el texto de error específico que está buscando.

En particular, mi problema era que estaba colocando líneas finales entre piezas de datos codificadas en URL. Cuando los saqué, todo funcionó. Es posible que pueda utilizar una técnica similar para conectarse a su servicio y leer el texto de error de respuesta real.


11
2017-07-19 23:02



Curiosamente, el HttpWebResponse.GetResponseStream() que obtienes de la WebException.Response no es lo mismo que el flujo de respuesta que recibiría del servidor. En nuestro entorno, estamos perdiendo respuestas reales del servidor cuando 400 estado HTTP el código se devuelve al cliente usando el HttpWebRequest/HttpWebResponse objetos. Por lo que hemos visto, el flujo de respuesta asociado con el WebException's HttpWebResponse se genera en el cliente y no incluye ningún cuerpo de respuesta del servidor. Muy frustrante, ya que queremos devolverle al cliente el motivo de la mala solicitud.


11
2018-04-20 15:29



Prueba esto (es VB-Code :-):

Try

Catch exp As WebException
  Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try

5
2018-03-25 15:02



Una versión asincrónica de la función de extensión:

    public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
    {
        try
        {
            return await request.GetResponseAsync();
        }
        catch(WebException ex)
        {
            return ex.Response;
        }
    }

3
2018-02-10 16:25