Verificar se HttpStatusCode representa sucesso ou falha


93

Vamos supor que eu tenha a seguinte variável:

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

Como posso verificar se este é um código de status de sucesso ou de falha?

Por exemplo, posso fazer o seguinte:

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

Também posso ter algum tipo de lista branca:

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

Nenhuma dessas alternativas me convence, e eu esperava por uma classe ou método .NET que pudesse fazer esse trabalho para mim, como:

bool isSuccess = HttpUtilities.IsSuccess(status);

você precisa fazer a int code = (int)Response.StatusCodepartir daí, você precisará criar seu próprio Enumcheque aqui para o exemplo de trabalho stackoverflow.com/questions/1330856/…
MethodMan

Você por acaso está usando a HttpClientclasse?
dcastro

1
@dcastro Não, sinto muito. Estou usando uma API de alto nível que pode (ou não) usar internamente. A API expõe o código de status da resposta, mas não expõe o interno, HttpResponseMessagepor exemplo
Matias Cicero

@MatiCicero Isso é muito ruim: / Você sempre pode reutilizar a implementação de HttpResponseMessage.IsSuccessStatusCode(veja minha resposta), que é exatamente igual à sua primeira abordagem, e torná-la um método de extensão no HttpStatusCodetipo.
dcastro

Respostas:


173

Se você estiver usando a HttpClientclasse, terá uma HttpResponseMessagevolta.

Esta classe tem uma propriedade útil chamada IsSuccessStatusCodeque fará a verificação para você.

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

Caso você esteja curioso, esta propriedade é implementada como:

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

Então você pode simplesmente reutilizar este algoritmo se você não usar HttpClientdiretamente.

Você também pode usar EnsureSuccessStatusCodepara lançar uma exceção caso a resposta não seja bem-sucedida.


FYI: Foi 'resposta. É bem-sucedida' para mim.
Nascimento de Topher em

Sua resposta é bastante útil, mas agora funciona assim: if (response.IsCompletedSuccessfully) {//}
salman

12

A classe HttpResponseMessage tem uma propriedade IsSuccessStatusCode, olhando para o código-fonte, é assim como usr já sugeriu 200-299 é provavelmente o melhor que você pode fazer.

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

11

A resposta aceita me incomoda um pouco, pois contém números mágicos, (embora estejam no padrão) em sua segunda parte. E a primeira parte não é genérica para códigos de status de inteiros simples, embora esteja perto da minha resposta.

Você poderia obter exatamente o mesmo resultado instanciando HttpResponseMessage com seu código de status e verificando o sucesso. Ele lança uma exceção de argumento se o valor for menor que zero ou maior que 999.

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

Isso não é exatamente conciso, mas você pode torná-lo uma extensão.


Isso funcionou perfeitamente para mim, pois eu tinha apenas um HttpStatusCode e não uma mensagem de resposta. Bom trabalho!
Todd Vance

5
"A resposta aceita me incomoda um pouco, pois contém números mágicos, (embora estejam no padrão)" - Eles não são "mágicos" se forem padronizados, bem compreendidos e nunca vão mudar. Não há absolutamente nada de errado em usar os códigos diretamente. Se você tiver, IsSuccessStatusCodeentão ótimo, use-o (como diz a resposta aceita.) Caso contrário, não adicione seu próprio lixo usando uma abstração, a menos que você esteja executando essa verificação em todo lugar
Ed S.

1
Lembre-se de que instanciar HttpResponseMessagepara usar uma de suas propriedades leva mais tempo do que verificar duas condições lógicas com int.
Miro J.

10

Adicionando a resposta @TomDoesCode Se você estiver usando HttpWebResponse, você pode adicionar este método de extensão:

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

8

Sou parcial quanto à descoberta de métodos de extensão.

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

Enquanto o seu namespace estiver no escopo, o uso estará statusCode.IsSuccessStatusCode().


2
você provavelmente quer asInt> = 200 lá
Jim O'Neil

Os métodos de extensão são legais, mas estou confuso - isso não faz a mesma coisa que a propriedade IsSuccessStatusCode do HTTPResponseMessage que é usada com HTTPClient ou IHTTPClientFactory? @DCastro até nos mostra que é implementado exatamente assim no .NET. Quando / por que eu usaria um método de extensão como este para códigos de status HTTP na faixa 2xx?
sfors diz restabelecer Monica de

4
@sfors, sim, mas e se você tiver apenas um HttpStatusCodeem escopo? Existem muitas bibliotecas que não usam ou aparecem, HttpResponseMessagemas fornecem o código de status.
bojingo

3

Depende de qual recurso HTTP você está chamando. Normalmente, o 2xxintervalo é definido como o intervalo de códigos de status de sucesso. Essa é claramente uma convenção que nem todo servidor HTTP seguirá.

Por exemplo, o envio de um formulário em um site geralmente retornará um redirecionamento 302.

Se você deseja desenvolver um método geral, a code >= 200 && code < 300ideia é provavelmente sua melhor chance.

Se você estiver chamando seu próprio servidor, provavelmente deve se certificar de padronizar 200.


2

Esta é uma extensão da resposta anterior, que evita a criação e posterior coleta de lixo de um novo objeto a cada invocação.

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);
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.