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

StackOverflow https://stackoverflow.com/questions/692342

  •  22-08-2019
  •  | 
  •  

Pregunta

Estoy en una situación en la que cuando llegue un HTTP 400 código del servidor, que es una manera completamente legal del servidor de decirme lo que estaba mal con mi solicitud (mediante un mensaje en el contenido de la respuesta HTTP)

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

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

¿Fue útil?

Solución

Sería bueno si había alguna manera de apagar "tirar el código no éxito", pero si se captura WebException al menos puede 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 como para encapsular el "dame una respuesta aún si no es un código de éxito" bit en un método separado. (Me gustaría sugerir que todavía tirar si no hay una respuesta, por ejemplo, si no se podía conectar.)

Si la respuesta de error puede ser grande (que es raro) es posible que desee ajustar HttpWebRequest.DefaultMaximumErrorResponseLength para asegurarse de obtener todo el error.

Otros consejos

Sé que esto ya ha sido contestada hace mucho tiempo, pero hice un método de extensión para ayudar esperemos que otras personas que vienen 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);
}

Curiosamente, el HttpWebResponse.GetResponseStream() que se obtiene de la WebException.Response no es la misma que la secuencia de respuesta que habría recibido del servidor. En nuestro entorno, estamos perdiendo las respuestas del servidor reales cuando un 400 de estado HTTP código se devuelve de nuevo al cliente usando los objetos HttpWebRequest/HttpWebResponse. De lo que hemos visto, la secuencia de respuesta asociado con el WebException's HttpWebResponse se genera en el cliente y no incluye ninguno de los cuerpo de la respuesta del servidor. Muy frustrante, ya que queremos mensaje de vuelta al cliente el motivo de la solicitud incorrecta.

he tenido problemas similares al intentar conectarse al servicio OAuth2 de Google.

Terminé escritura de entradas manualmente, sin utilizar WebRequest, como esto:

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 a la secuencia de respuesta contiene el texto de error específico que usted está buscando.

En particular, mi problema era que yo estaba poniendo líneas de fondo entre las piezas de datos con codificación URL. Cuando los saqué, todo funcionaba. Usted puede ser capaz de utilizar una técnica similar para conectarse a su servicio y leer el texto de error de respuesta real.

Probar (es VB-Code: -):

Try

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

Una versión asíncrona de 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;
        }
    }

Esto resolvió por mí:
https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77

TL; DR:
Problema:
vuelve localhost esperadas de contenido, IP remota altera el contenido a 400 "Solicitud incorrecta"
Solución:
Añadiendo <httpErrors existingResponse="PassThrough"></httpErrors> a web.config/configuration/system.webServer resuelve esto para mí; Ahora todos los servidores (locales y remotas) devuelven el mismo contenido exacto (generada por mí), independientemente de la dirección IP y / o código HTTP que regrese.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top