¿Cómo obtengo StatusCode de HttpRequestException?

87

Probablemente me esté perdiendo algo obvio aquí.

Estoy usando los HttpClientlanzamientos HttpRequestExceptionque contienen StatusCodeen la cadena de mensajes.

¿Cómo puedo acceder a eso StatusCode?


Editar : Más información, escribí esta pregunta apresuradamente.

Estoy usando HttpClientpara acceder a otra API dentro de mi proyecto WebApi. Sí, sé por qué llamo EnsureSuccessStatusCode(). Quiero propagar algunos errores en sentido descendente, como 404 y 403.

Todo lo que quería era transformarme constantemente HttpRequestExceptionen el HttpResponseExceptionuso de personalización ExceptionFilterAttribute.

Desafortunadamente, HttpRequestExceptionno contiene ninguna información adicional que pueda usar además del mensaje. Esperaba descubrir StatusCodeen forma cruda (int o enum).

Parece que puedo:

  1. Use el mensaje para cambiar el código de estado (bleh)
  2. O cree mi versión de SecureSuccessStatusCode y lance una excepción que sea realmente útil.
Kugel
fuente
1
¿Puedes mostrar un fragmento de código?
Hamlet Hakobyan
1
¿Qué quieres decir con "acceder a ese código de estado"?
Marco
Muestre el código para indicar dónde está obteniendo la excepción.
danés
5
Chicos, ¿qué no está claro sobre el título de esta pregunta?
Kugel
1
¿Consiguió encontrar alguna solución adecuada a este problema? por favor comparta
Siddharth Pandey

Respuestas:

37

El código de estado se pasó como parte de una cadena para HttpRequestExceptionque no pueda recuperarlo solo de tales excepciones.

El diseño de System.Net.Httprequiere que acceda en HttpResponseMessage.StatusCodelugar de esperar la excepción.

http://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage(v=vs.110).aspx

Si ahora está siguiendo la guía de Microsoft , asegúrese de comprender claramente por qué le pide que llame HttpResponseMessage.EnsureSucessStatusCode. Si no llama a esa función, no debería haber ninguna excepción.

Lex Li
fuente
2
Estoy tratando de abordar una preocupación transversal aquí. Mira mi edición, tal vez haya una mejor solución.
Kugel
1
¿Esto encaja con el uso de HttpClient.GetStreamAsync (url) ya que no veo una forma de realizar esta acción sin tener que quitar el texto del mensaje?
El senador
1
@TheSenator Tienes que llamar a GetAsync (uri) o PostAsync (uri) para recuperar un HttpResponseMessage. Si intenta obtener el contenido de la respuesta, ya sea leyéndola o utilizando un método de conveniencia como GetStreamAsync, se llama a GuaranteSuccessStatusCode bajo el capó.
odyth
6
Lo que plantea la pregunta obvia de cuál es el sentido de que los métodos de conveniencia estén disponibles si arrojan excepciones que no permiten manejar el error de manera útil. Tirar su código con declaraciones if y throw no es una solución, por lo que, por lo que se ha dicho aquí, parece que la respuesta correcta actualmente es que debe volver a implementar los métodos de conveniencia o GarantizarSuccessStatusCode usted mismo.
Neutrino
1
Es más fácil decirlo que hacerlo. La excepción se puede lanzar desde un código de terceros. Por ejemplo, cliente swagger generado automáticamente.
user2555515
27

Por lo que vale, este tipo hizo algo inteligente: https://social.msdn.microsoft.com/Forums/vstudio/en-US/dc9bc426-1654-4319-a7fb-383f00b68def/c-httpresponsemessage-throws-exception-httprequestexception -webexception-the-remote-name? forum = csharpgeneral

En el caso de que necesite una propiedad de estado de excepción, puedo hacer esto:

catch (HttpRequestException requestException)
{
    if (requestException.InnerException is WebException webException && webException.Status == WebExceptionStatus.NameResolutionFailure)
    {
        return true;
    }

    return false;
}
Steve
fuente
14
votado porque a veces no tiene acceso a la respuesta, como cuando se ve obligado a usar una biblioteca que envuelve la funcionalidad y arroja cualquier excepción.
Kell
4
el .net core 2.1 HttpClient tiene GetAsync () y GetStreamAsync (). El primero devolverá una respuesta, mientras que el otro llamará SecureSucessStatusCode internamente y lanzará una HttpRequestException. No entiendo la inconsistencia y dificulta el manejo de errores, pero aprecio esta solución.
smurtagh
2
La ejecución de .NET Core 3.1.5 requestException.InnerExceptiones nula, por lo que esto no funcionará
Ohad Schneider
3

Como también lo mencionaron otros, no es una buena práctica obtener el StatusCode de HttpRequestException, lo mismo se puede hacer de antemano con HttpResponseMessage.StatusCode después de verificar HttpResponseMessage.IsSuccessStatusCode

De todos modos, si debido a alguna restricción / requisito, uno tiene que leer StatusCode, puede haber dos soluciones

  1. Amplió el HttpResponseMessage con su excepción personalizada explicada aquí
  2. Hackear el HttpRequestException.ToString para obtener el StatusCode, ya que el mensaje es una publicación constante fijada por StatusCode y Repharse.

A continuación se muestra el código en System.Net.Http.HttpResponseMessage donde SR.net_http_message_not_success_statuscode = "El código de estado de respuesta no indica éxito: {0} ({1})".

public HttpResponseMessage EnsureSuccessStatusCode()
    {
        if (!this.IsSuccessStatusCode)
        {
            if (this.content != null)
            {
                this.content.Dispose();
            }
            throw new HttpRequestException(string.Format(CultureInfo.InvariantCulture, SR.net_http_message_not_success_statuscode, new object[]
            {
                (int)this.statusCode,
                this.ReasonPhrase
            }));
        }
        return this;
    }
Surender Singh Malik
fuente
4
Las cadenas de error con un formato específico son un olor a código, la lógica nunca debería depender de ellas.
user1496062
1
@ user1496062 Cuando los errores provienen de un sistema externo, a menudo no hay alternativa.
Ian Warburton
1

Esto ha funcionado para mi

var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
Rastislav Bodorik
fuente