Überprüfen, ob HttpStatusCode Erfolg oder Misserfolg darstellt

93

Nehmen wir an, ich habe die folgende Variable:

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

Wie kann ich überprüfen, ob dies ein Erfolgsstatuscode oder ein Fehlercode ist?

Zum Beispiel kann ich Folgendes tun:

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

Ich kann auch eine Art weiße Liste haben:

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

Keine dieser Alternativen überzeugt mich und ich hatte auf eine .NET-Klasse oder -Methode gehofft, die diese Arbeit für mich erledigen kann, wie zum Beispiel:

bool isSuccess = HttpUtilities.IsSuccess(status);
Matias Cicero
quelle
Sie tun müssen , um int code = (int)Response.StatusCodevon dort aus müssen Sie Ihre eigene erstellen EnumCheck hier für das Arbeitsbeispiel stackoverflow.com/questions/1330856/...
MethodMan
Benutzt du zufällig die HttpClientKlasse?
Dcastro
1
@dcastro Nein, tut mir leid. Ich verwende eine High-Level- API, die sie möglicherweise intern verwendet (oder auch nicht). Die API stellt den Statuscode der Antwort, aber nicht ausgesetzt sind nicht die inneren HttpResponseMessagezum Beispiel
Matias Cicero
@MatiCicero Das ist schade: / Sie können die Implementierung von HttpResponseMessage.IsSuccessStatusCode(siehe meine Antwort), die genau Ihrem ersten Ansatz entspricht, jederzeit wiederverwenden und sie zu einer Erweiterungsmethode für den HttpStatusCodeTyp machen.
Dcastro

Antworten:

172

Wenn Sie die HttpClientKlasse verwenden, erhalten Sie eine HttpResponseMessageRückerstattung.

Diese Klasse hat eine nützliche Eigenschaft namens IsSuccessStatusCode, die die Prüfung für Sie durchführt.

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

Falls Sie neugierig sind, wird diese Eigenschaft wie folgt implementiert :

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

So können Sie einfach diesen Algorithmus wiederverwenden , wenn Sie nicht mit HttpClientdirekt.

Sie können auch EnsureSuccessStatusCodeeine Ausnahme auslösen, falls die Antwort nicht erfolgreich war.

dcastro
quelle
Zu Ihrer Information: War für mich 'response.IsSuccessful'.
Topher Geburt
Ihre Antwort ist sehr hilfreich, aber jetzt funktioniert es wie
folgt
12

Die HttpResponseMessage-Klasse verfügt über eine IsSuccessStatusCode-Eigenschaft. Wenn Sie den Quellcode so betrachten, ist dies wahrscheinlich das Beste, was Sie tun können, da usr bereits vorgeschlagen hat, 200-299 zu verwenden.

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

Die akzeptierte Antwort stört mich ein wenig, da sie im zweiten Teil magische Zahlen enthält (obwohl sie im Standard sind). Und der erste Teil ist nicht generisch für einfache ganzzahlige Statuscodes, obwohl er meiner Antwort nahe kommt.

Sie können genau das gleiche Ergebnis erzielen, indem Sie HttpResponseMessage mit Ihrem Statuscode instanziieren und auf Erfolg prüfen. Es wird eine Argumentausnahme ausgelöst, wenn der Wert kleiner als Null oder größer als 999 ist.

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

Dies ist nicht gerade prägnant, aber Sie könnten es zu einer Erweiterung machen.

user232548
quelle
Dies funktionierte perfekt für mich, da ich nur einen HttpStatusCode und keine Antwortnachricht hatte. Gut gemacht!
Todd Vance
5
"Die akzeptierte Antwort stört mich ein wenig, da sie magische Zahlen enthält (obwohl sie im Standard sind)" - Sie sind keine "Magie", wenn sie standardisiert, gut verstanden und sich nie ändern werden. Es ist absolut nichts Falsches daran, die Codes direkt zu verwenden. Wenn Sie IsSuccessStatusCodedann großartig sind, verwenden Sie es (wie in der akzeptierten Antwort angegeben). Andernfalls fügen Sie Ihre eigene Cruft nicht mithilfe einer Abstraktion hinzu, es sei denn, Sie führen diese Prüfung überall durch
Ed S.
1
Beachten Sie, dass das Instanziieren HttpResponseMessageder Verwendung einer seiner Eigenschaften mehr Zeit in Anspruch nimmt als das Überprüfen von zwei logischen Bedingungen mit int.
Miro J.
10

Hinzufügen zur @ TomDoesCode-Antwort Wenn Sie HttpWebResponse verwenden, können Sie diese Erweiterungsmethode hinzufügen:

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

Ich bin an der Auffindbarkeit von Erweiterungsmethoden interessiert.

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

Solange sich Ihr Namespace im Gültigkeitsbereich befindet, wird verwendet statusCode.IsSuccessStatusCode().

bojingo
quelle
2
Sie wollen wahrscheinlich asInt> = 200 dort
Jim O'Neil
Erweiterungsmethoden sind cool, aber ich bin verwirrt. Funktioniert dies nicht mit der IsSuccessStatusCode-Eigenschaft von HTTPResponseMessage, die mit dem HTTPClient oder der IHTTPClientFactory verwendet wird? @DCastro zeigt uns sogar, dass es genau so in .NET implementiert ist. Wann / warum sollte ich eine solche Erweiterungsmethode für HTTP-Statuscodes im Bereich 2xx verwenden?
Sfors sagt, Monica
4
@sfors, ja, aber was ist, wenn Sie nur einen HttpStatusCodeUmfang haben? Es gibt viele Bibliotheken, die nicht verwenden oder auftauchen, HttpResponseMessageaber Ihnen den Statuscode geben.
Bojingo
3

Dies hängt davon ab, welche HTTP-Ressource Sie aufrufen. Normalerweise wird der 2xxBereich als Bereich der Erfolgsstatuscodes definiert. Dies ist eindeutig eine Konvention, die nicht jeder HTTP-Server einhalten wird.

Wenn Sie beispielsweise ein Formular auf einer Website senden, wird häufig eine 302-Weiterleitung zurückgegeben.

Wenn Sie eine allgemeine Methode entwickeln möchten, ist die code >= 200 && code < 300Idee wahrscheinlich die beste.

Wenn Sie Ihren eigenen Server anrufen, sollten Sie wahrscheinlich sicherstellen, dass Sie standardisieren 200.

usr
quelle
2

Dies ist eine Erweiterung der vorherigen Antwort, die die Erstellung und anschließende Speicherbereinigung eines neuen Objekts für jeden Aufruf vermeidet.

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
quelle