Como obtenho StatusCode de HttpRequestException?


87

Provavelmente estou perdendo algo óbvio aqui.

Estou usando o HttpClientque lança HttpRequestExceptionque contém StatusCodena string Message.

Como posso acessar isso StatusCode?


Edit : Mais informações, escrevi esta pergunta com pressa.

Estou usando HttpClientpara acessar outra API dentro do meu projeto WebApi. Sim, eu sei por que estou ligando EnsureSuccessStatusCode(). Desejo propagar alguns erros posteriores, como 404 e 403.

Tudo o que eu queria era me transformar de forma consistente HttpRequestExceptionno HttpResponseExceptionuso personalizado ExceptionFilterAttribute.

Infelizmente, HttpRequestExceptionnão contém nenhuma informação extra que eu possa usar além da mensagem. Eu esperava descobrir StatusCodena forma bruta (int ou enum).

Parece que posso:

  1. Use a mensagem para mudar o código de status (bleh)
  2. Ou crie minha versão de EnsureSuccessStatusCode e lança uma exceção que é realmente utilizável.

1
Você pode mostrar um trecho de código?
Hamlet Hakobyan

1
O que você quer dizer com "acessar esse código de status"?
Marco

Mostrar o código informa onde você está obtendo a exceção.
dinamarquês,

5
Pessoal, o que não está claro sobre o título dessa pergunta?
Kugel

1
Você conseguiu encontrar alguma solução adequada para este problema? compartilhe
Siddharth Pandey

Respostas:


37

O código de status foi passado como parte de uma string para, de HttpRequestExceptionmodo que você não pode recuperá-lo apenas de tais exceções.

O design do System.Net.Httprequer que você acesse em HttpResponseMessage.StatusCodevez de esperar pela exceção.

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

Se agora você está seguindo o guia da Microsoft , certifique-se de entender claramente por que ele pede para você ligar HttpResponseMessage.EnsureSucessStatusCode. Se você não chamar essa função, não deve haver exceção.


2
Estou tentando abordar uma questão transversal, aqui. Olhe minha edição, talvez haja uma solução melhor.
Kugel

1
Isso se encaixa com o uso de HttpClient.GetStreamAsync (url), pois não consigo ver uma maneira de realizar essa ação sem ter que remover o texto da mensagem?
O senador

1
@TheSenator Você deve chamar GetAsync (uri) ou PostAsync (uri) para obter um HttpResponseMessage. Se você tentar obter o conteúdo da resposta lendo-a ou usando um método de conveniência como GetStreamAsync, VerifySuccessStatusCode é chamado por baixo do capô.
dia

6
O que levanta a questão óbvia de qual é o objetivo dos métodos de conveniência estarem disponíveis se eles lançam exceções que não tornam possível manipular o erro de forma útil. Desordenar seu código com instruções if e throw não é solução, portanto, pelo que foi dito aqui, parece que a resposta correta atualmente é que você mesmo deve reimplementar os métodos de conveniência ou VerifySuccessStatusCode sozinho.
Neutrino

1
É mais fácil falar do que fazer. A exceção pode ser lançada a partir de um código de terceiros. Por exemplo, cliente de swagger gerado automaticamente.
user2555515

27

Para valer a pena, esse cara fez algo inteligente: https://social.msdn.microsoft.com/Forums/vstudio/en-US/dc9bc426-1654-4319-a7fb-383f00b68def/c-httpresponsemessage-throws-exception-httprequestexception -webexception-the-remote-name? forum = csharpgeneral

No caso de eu precisar de uma propriedade de status de exceção, posso fazer o seguinte:

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

    return false;
}

14
votado porque às vezes você não tem acesso à resposta, como quando é forçado a usar uma biblioteca que envolve a funcionalidade e lança quaisquer exceções.
Kell

4
o .net core 2.1 HttpClient tem GetAsync () e GetStreamAsync (). O primeiro retornará uma resposta, enquanto o outro chamará EnsureSucessStatusCode internamente e lança uma HttpRequestException. Não entendo a inconsistência e isso dificulta o tratamento de erros, mas agradeço essa solução alternativa.
smurtagh

2
A execução do .NET Core 3.1.5 requestException.InnerExceptioné nula, então não funcionará
Ohad Schneider

3

Como mencionado por outros também, não é uma boa prática obter o StatusCode de HttpRequestException, o mesmo pode ser feito de antemão com HttpResponseMessage.StatusCode após verificar HttpResponseMessage.IsSuccessStatusCode

De qualquer forma, se devido a alguma restrição / requisito for necessário ler StatusCode, pode haver duas soluções

  1. Estendeu o HttpResponseMessage com sua exceção personalizada explicada aqui
  2. Hackeie HttpRequestException.ToString para obter o StatusCode, já que a mensagem é uma postagem constante corrigida por StatusCode e Repharse.

Abaixo está o código em System.Net.Http.HttpResponseMessage Onde SR.net_http_message_not_success_statuscode = "Código de status de resposta não indica sucesso: {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;
    }

4
strings de erro com um formato específico são um cheiro de código, a lógica nunca deve depender deles.
user1496062

1
@ user1496062 Quando os erros vêm de um sistema externo, geralmente não há alternativa.
Ian Warburton

1

Isso tem funcionado para mim

var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
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.