Verifica se HttpStatusCode rappresenta il successo o il fallimento


93

Supponiamo di avere la seguente variabile:

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

Come posso verificare se si tratta di un codice di stato di successo o di un errore?

Ad esempio, posso fare quanto segue:

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

Posso anche avere una sorta di lista bianca:

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

Nessuna di queste alternative mi convince e speravo in una classe o un metodo .NET che potesse fare questo lavoro per me, come ad esempio:

bool isSuccess = HttpUtilities.IsSuccess(status);

è necessario fare int code = (int)Response.StatusCodeda lì è necessario creare il proprio Enumassegno qui per lavorare ad esempio stackoverflow.com/questions/1330856/...
Method Man

Stai per caso usando la HttpClientclasse?
dcastro

1
@dcastro No, mi dispiace. Sto utilizzando un'API di alto livello che può (o non può) utilizzarla internamente. L'API espone il codice di stato della risposta, ma non espone l'interno, HttpResponseMessagead esempio
Matias Cicero,

@MatiCicero È un peccato: / Puoi sempre riutilizzare l'implementazione di HttpResponseMessage.IsSuccessStatusCode(vedi la mia risposta) che è esattamente la stessa del tuo primo approccio e renderlo un metodo di estensione sul HttpStatusCodetipo.
dcastro

Risposte:


173

Se stai usando la HttpClientclasse, avrai una HttpResponseMessagerisposta.

Questa classe ha una proprietà utile chiamata IsSuccessStatusCodeche farà il controllo per te.

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

Nel caso foste curiosi, questa proprietà è implementata come:

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

Quindi, si può semplicemente riutilizzare questo algoritmo, se stai non usando HttpClientdirettamente.

È inoltre possibile utilizzare EnsureSuccessStatusCodeper generare un'eccezione nel caso in cui la risposta non abbia avuto successo.


Cordiali saluti: è stato "response.IsSuccessful" per me.
Nascita di Topher il

La tua risposta è abbastanza utile ma ora funziona come: if (response.IsCompletedSuccessfully) {//}
salman

12

La classe HttpResponseMessage ha una proprietà IsSuccessStatusCode, guardando il codice sorgente è così, quindi come usr ha già suggerito 200-299 è probabilmente il meglio che puoi fare.

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

11

La risposta accettata mi dà un po 'fastidio in quanto contiene numeri magici, (sebbene siano nello standard) nella sua seconda parte. E la prima parte non è generica per semplici codici di stato interi, sebbene sia vicina alla mia risposta.

È possibile ottenere esattamente lo stesso risultato creando un'istanza di HttpResponseMessage con il codice di stato e verificandone l'esito positivo. Genera un'eccezione di argomento se il valore è minore di zero o maggiore di 999.

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

Non è esattamente conciso, ma potresti renderlo un'estensione.


Questo ha funzionato perfettamente per me poiché avevo solo un HttpStatusCode e non un messaggio di risposta. Buon lavoro!
Todd Vance

5
"La risposta accettata mi infastidisce un po 'perché contiene numeri magici, (sebbene siano nello standard)" - Non sono "magici" se sono standardizzati, ben compresi e non cambieranno mai. Non c'è assolutamente niente di sbagliato nell'usare i codici direttamente. Se hai un IsSuccessStatusCodeottimo risultato, usalo (come dice la risposta accettata). Altrimenti, non aggiungere il tuo cruft usando un'astrazione a meno che tu non stia eseguendo questo controllo dappertutto
Ed S.

1
Tieni presente che la creazione HttpResponseMessagedi istanze per utilizzare una delle sue proprietà richiede più tempo rispetto al controllo di due condizioni logiche con int.
Miro J.

10

Aggiunta alla risposta @TomDoesCode Se stai usando HttpWebResponse puoi aggiungere questo metodo di estensione:

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

8

Sono parziale alla scoperta dei metodi di estensione.

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

Finché il tuo spazio dei nomi è nell'ambito, l'utilizzo sarebbe statusCode.IsSuccessStatusCode().


2
probabilmente vuoi asInt> = 200 lì
Jim O'Neil

I metodi di estensione sono interessanti, ma sono confuso: non fa la stessa cosa della proprietà IsSuccessStatusCode di HTTPResponseMessage utilizzata con HTTPClient o IHTTPClientFactory? @DCastro ci mostra anche che è implementato esattamente in questo modo in .NET. Quando / perché dovrei utilizzare un metodo di estensione come questo per i codici di stato HTTP nell'intervallo 2xx?
sfors dice reintegrare Monica il

4
@sfors, sì, ma cosa succede se hai solo un HttpStatusCodeambito? Ci sono molte librerie che non usano o non emergono HttpResponseMessagema ti danno il codice di stato.
bojingo

3

Dipende dalla risorsa HTTP che stai chiamando. Di solito, l' 2xxintervallo è definito come l'intervallo di codici di stato di successo. Questa è chiaramente una convenzione a cui non tutti i server HTTP aderiranno.

Ad esempio, l'invio di un modulo su un sito Web restituirà spesso un reindirizzamento 302.

Se vuoi escogitare un metodo generale, l' code >= 200 && code < 300idea è probabilmente il tuo colpo migliore.

Se si sta chiamando il vostro proprio assistente allora probabilmente dovrebbe fare in modo che si standardizzare su 200.


2

Questa è un'estensione della risposta precedente, che evita la creazione e la successiva garbage collection di un nuovo oggetto per ogni invocazione.

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);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.