Comment obtenir StatusCode de HttpRequestException?

87

Il me manque probablement quelque chose d'évident ici.

J'utilise les HttpClientlancers HttpRequestExceptionqui contiennent StatusCodedans la chaîne Message.

Comment puis-je y accéder StatusCode?


Edit : Plus d'infos, j'ai écrit cette question dans la précipitation.

J'utilise HttpClientpour accéder à une autre API dans mon projet WebApi. Oui, je sais pourquoi j'appelle EnsureSuccessStatusCode(). Je veux propager certaines erreurs en aval telles que 404 et 403.

Tout ce que je voulais, c'était de toujours me transformer HttpRequestExceptionen HttpResponseExceptionutilisation personnalisée ExceptionFilterAttribute.

Malheureusement, HttpRequestExceptionne contient aucune information supplémentaire que je pourrais utiliser en plus du message. J'espérais découvrir StatusCodesous forme brute (int ou enum).

On dirait que je peux:

  1. Utilisez le message pour changer le code d'état (bleh)
  2. Ou créez ma version d'EnsureSuccessStatusCode et lancez une exception qui est réellement utilisable.
Kugel
la source
1
Pouvez-vous montrer un morceau de code?
Hamlet Hakobyan
1
Qu'entendez-vous par «accéder à ce code d'état»?
Marco
Montrez le code indiquant où vous obtenez l'exception.
danois
5
Les gars, qu'est-ce qui n'est pas clair sur le titre de cette question?
Kugel
1
Avez-vous réussi à trouver une solution appropriée à ce problème? s'il vous plaît partager
Siddharth Pandey

Réponses:

37

Le code d'état a été transmis dans le cadre d'une chaîne à HttpRequestExceptionafin que vous ne puissiez pas le récupérer uniquement à partir de telles exceptions.

La conception de System.Net.Httpvous oblige à accéder HttpResponseMessage.StatusCodeau lieu d'attendre l'exception.

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

Si vous suivez maintenant le guide Microsoft , assurez-vous de bien comprendre pourquoi il vous demande d'appeler HttpResponseMessage.EnsureSucessStatusCode. Si vous n'appelez pas cette fonction, il ne devrait y avoir aucune exception.

Lex Li
la source
2
J'essaie de répondre à une préoccupation transversale, ici. Regardez mon montage, il y a peut-être une meilleure solution.
Kugel
1
Cela correspond-il à l'utilisation de HttpClient.GetStreamAsync (url) car je ne vois pas un moyen d'effectuer cette action sans avoir à supprimer le texte du message?
The Senator
1
@TheSenator Vous devez appeler GetAsync (uri) ou PostAsync (uri) pour récupérer un HttpResponseMessage. Si vous essayez d'accéder au contenu de la réponse en la lisant ou en utilisant une méthode pratique comme GetStreamAsync, EnsureSuccessStatusCode est appelé sous le capot.
odyth
6
Ce qui soulève la question évidente de savoir quel est l'intérêt des méthodes de commodité disponibles si elles lancent des exceptions qui ne permettent pas de gérer utilement l'erreur. Jeter votre code avec des instructions if et throw n'est pas une solution, donc d'après ce qui a été dit ici, il semble que la réponse correcte soit actuellement que vous devez réimplémenter les méthodes de commodité ou EnsureSuccessStatusCode vous-même.
Neutrino
1
C'est plus facile à dire qu'à faire. L'exception peut être levée à partir d'un code tiers. Par exemple, un client swagger généré automatiquement.
user2555515
27

Pour ce que ça vaut, ce gars a fait quelque chose d'intelligent: https://social.msdn.microsoft.com/Forums/vstudio/en-US/dc9bc426-1654-4319-a7fb-383f00b68def/c-httpresponsemessage-throws-exception-httprequestexception -webexception-le-nom-distant? forum = csharpgeneral

Dans le cas où j'ai besoin d'une propriété de statut d'exception, je peux le faire:

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

    return false;
}
Steve
la source
14
voté à la hausse parce que parfois vous n'avez pas accès à la réponse, comme lorsque vous êtes obligé d'utiliser une bibliothèque qui encapsule la fonctionnalité et lève des exceptions.
Kell le
4
le .net core 2.1 HttpClient a GetAsync () et GetStreamAsync (). Le premier renverra une réponse tandis que l'autre appellera EnsureSucessStatusCode en interne et lèvera une HttpRequestException. Je ne comprends pas l'incohérence et cela rend la gestion des erreurs difficile, mais j'apprécie cette solution de contournement.
smurtagh
2
Exécuter .NET Core 3.1.5, requestException.InnerExceptionest nul, donc cela ne fonctionnera pas
Ohad Schneider
3

Comme mentionné par d'autres également, ce n'est pas une bonne pratique d'obtenir le StatusCode de HttpRequestException, la même chose peut être faite au préalable avec HttpResponseMessage.StatusCode après avoir vérifié HttpResponseMessage.IsSuccessStatusCode

Quoi qu'il en soit, si en raison d'une contrainte / exigence, on doit lire StatusCode, il peut y avoir deux solutions

  1. Étendu le HttpResponseMessage avec votre exception personnalisée expliquée ici
  2. Piratez le HttpRequestException.ToString pour obtenir le StatusCode, car le message est un message constant fixé par StatusCode et Repharse.

Voici le code dans System.Net.Http.HttpResponseMessage Where SR.net_http_message_not_success_statuscode = "Le code d'état de la réponse n'indique pas le succès: {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
la source
4
les chaînes d'erreur avec un format spécifique sont une odeur de code, la logique ne devrait jamais en dépendre.
user1496062
1
@ user1496062 Lorsque les erreurs proviennent d'un système externe, il n'y a souvent pas d'alternative.
Ian Warburton
1

Cela a fonctionné pour moi

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