Vérifier si HttpStatusCode représente le succès ou l'échec

93

Supposons que j'ai la variable suivante:

System.Net.HttpStatusCode status = System.Net.HttpStatusCode.OK;

Comment puis-je vérifier s'il s'agit d'un code d'état de réussite ou d'échec?

Par exemple, je peux faire ce qui suit:

int code = (int)status;
if(code >= 200 && code < 300) {
    //Success
}

Je peux aussi avoir une sorte de liste blanche:

HttpStatusCode[] successStatus = new HttpStatusCode[] {
     HttpStatusCode.OK,
     HttpStatusCode.Created,
     HttpStatusCode.Accepted,
     HttpStatusCode.NonAuthoritativeInformation,
     HttpStatusCode.NoContent,
     HttpStatusCode.ResetContent,
     HttpStatusCode.PartialContent
};
if(successStatus.Contains(status)) //LINQ
{
    //Success
}

Aucune de ces alternatives ne me convainc, et j'espérais une classe ou une méthode .NET capable de faire ce travail pour moi, telle que:

bool isSuccess = HttpUtilities.IsSuccess(status);
Matias Cicero
la source
vous devez faire à int code = (int)Response.StatusCodepartir de là, vous devrez créer votre propre Enumchèque ici pour un exemple de travail stackoverflow.com/questions/1330856/…
MethodMan
Utilisez-vous par hasard la HttpClientclasse?
dcastro le
1
@dcastro Non, je suis désolé. J'utilise une API de haut niveau qui peut (ou non) l'utiliser en interne. L'API expose le code d'état de la réponse, mais n'expose pas l'intérieur HttpResponseMessagepar exemple
Matias Cicero
@MatiCicero C'est dommage: / Vous pouvez toujours réutiliser l'implémentation de HttpResponseMessage.IsSuccessStatusCode(voir ma réponse) qui est exactement la même que votre première approche, et en faire une méthode d'extension sur le HttpStatusCodetype.
dcastro le

Réponses:

173

Si vous utilisez la HttpClientclasse, vous obtiendrez un HttpResponseMessageremboursement.

Cette classe a une propriété utile appelée IsSuccessStatusCodequi effectuera la vérification pour vous.

using (var client = new HttpClient())
{
    var response = await client.PostAsync(uri, content);
    if (response.IsSuccessStatusCode)
    {
        //...
    }
}

Au cas où vous êtes curieux, cette propriété est implémentée comme:

public bool IsSuccessStatusCode
{
    get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); }
}

Vous pouvez donc simplement réutiliser cet algorithme si vous ne l' utilisez pasHttpClient directement.

Vous pouvez également utiliser EnsureSuccessStatusCodepour lever une exception au cas où la réponse échouerait.

dcastro
la source
FYI: Était «la réponse, le succès» pour moi.
Topher Naissance le
Votre réponse est très utile mais maintenant elle fonctionne comme: if (response.IsCompletedSuccessfully) {//}
salman
12

La classe HttpResponseMessage a une propriété IsSuccessStatusCode, en regardant le code source, c'est comme ça, comme usr l'a déjà suggéré, 200-299 est probablement le mieux que vous puissiez faire.

public bool IsSuccessStatusCode
{
    get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); }
}
TomDoesCode
la source
11

La réponse acceptée me dérange un peu car elle contient des nombres magiques, (bien qu'ils soient en standard) dans sa deuxième partie. Et la première partie n'est pas générique pour les codes d'état entiers simples, bien qu'elle soit proche de ma réponse.

Vous pouvez obtenir exactement le même résultat en instanciant HttpResponseMessage avec votre code d'état et en vérifiant le succès. Il lève une exception d'argument si la valeur est inférieure à zéro ou supérieure à 999.

if (new HttpResponseMessage((HttpStatusCode)statusCode).IsSuccessStatusCode)
{
    // ...
}

Ce n'est pas exactement concis, mais vous pouvez en faire une extension.

utilisateur232548
la source
Cela a parfaitement fonctionné pour moi car je n'avais qu'un HttpStatusCode et non un message de réponse. Bon travail!
Todd Vance
5
"La réponse acceptée me dérange un peu car elle contient des nombres magiques, (bien qu'ils soient en standard)" - Ils ne sont pas "magiques" s'ils sont standardisés, bien compris et ne changeront jamais. Il n'y a absolument rien de mal à utiliser les codes directement. Si vous avez IsSuccessStatusCodealors super, utilisez-le (comme le dit la réponse acceptée.) Sinon, n'ajoutez pas votre propre cruft en utilisant une abstraction à moins que vous n'effectuiez cette vérification partout
Ed S.
1
Gardez à l'esprit que l'instanciation HttpResponseMessagepour utiliser l'une de ses propriétés prend plus de temps que la vérification de deux conditions logiques avec int.
Miro J.
10

Ajout à la réponse @TomDoesCode Si vous utilisez HttpWebResponse, vous pouvez ajouter cette méthode d'extension:

public static bool IsSuccessStatusCode(this HttpWebResponse httpWebResponse)
{
    return ((int)httpWebResponse.StatusCode >= 200) && ((int)httpWebResponse.StatusCode <= 299);
}
ozba
la source
8

Je suis partisan de la découvrabilité des méthodes d'extension.

public static class HttpStatusCodeExtensions
{
    public static bool IsSuccessStatusCode(this HttpStatusCode statusCode)
    {
        var asInt = (int)statusCode;
        return asInt >= 200 && asInt <= 299;
    }
}

Tant que votre espace de noms est dans la portée, l'utilisation serait statusCode.IsSuccessStatusCode().

bojingo
la source
2
vous voulez probablement asInt> = 200 there
Jim O'Neil
Les méthodes d'extension sont cool, mais je suis confus - cela ne fait-il pas la même chose que la propriété IsSuccessStatusCode de HTTPResponseMessage qui est utilisée avec HTTPClient ou IHTTPClientFactory? @DCastro nous montre même qu'il est implémenté exactement comme ça dans .NET. Quand / pourquoi utiliser une méthode d'extension comme celle-ci pour les codes d'état HTTP dans la plage 2xx?
sfors dit de réintégrer Monica
4
@sfors, oui, mais que faire si vous n'avez qu'un HttpStatusCodechamp d'application? Il existe de nombreuses bibliothèques qui n'utilisent pas ou ne font pas surface, HttpResponseMessagemais qui vous donnent le code d'état.
bojingo
3

Cela dépend de la ressource HTTP que vous appelez. Habituellement, le2xx plage est définie comme la plage de codes d'état de réussite. C'est clairement une convention à laquelle tous les serveurs HTTP n'adhéreront pas.

Par exemple, la soumission d'un formulaire sur un site Web renverra souvent une redirection 302.

Si vous souhaitez concevoir une méthode générale, l' code >= 200 && code < 300idée est probablement la meilleure solution.

Si vous appelez votre propre serveur, vous devriez probablement vous assurer que vous standardisez sur 200.

usr
la source
2

Il s'agit d'une extension de la réponse précédente, qui évite la création et le garbage collection ultérieur d'un nouvel objet pour chaque appel.

public static class StatusCodeExtensions
{
    private static readonly ConcurrentDictionary<HttpStatusCode, bool> IsSuccessStatusCode = new ConcurrentDictionary<HttpStatusCode, bool>();
    public static bool IsSuccess(this HttpStatusCode statusCode) => IsSuccessStatusCode.GetOrAdd(statusCode, c => new HttpResponseMessage(c).IsSuccessStatusCode);
}
Rob Lyndon
la source