Jak uzyskać StatusCode z HttpRequestException?

87

Prawdopodobnie brakuje mi tutaj czegoś oczywistego.

Używam HttpClientrzutów, HttpRequestExceptionktóre zawierają StatusCodew ciągu Message.

Jak mogę uzyskać do tego dostęp StatusCode?


Edycja : Więcej informacji, napisałem to pytanie w pośpiechu.

Używam HttpClientdostępu do innego interfejsu API w moim projekcie WebApi. Tak, wiem, dlaczego dzwonię EnsureSuccessStatusCode(). Chcę propagować niektóre błędy w dół, takie jak 404 i 403.

Jedyne, czego chciałem, to konsekwentne przekształcanie się HttpRequestExceptionw HttpResponseExceptionużywanie niestandardowych ExceptionFilterAttribute.

Niestety HttpRequestExceptionoprócz wiadomości nie zawiera żadnych dodatkowych informacji, których mógłbym użyć. Miałem nadzieję, że uda mi się to odkryć StatusCodew formie surowej (int lub enum).

Wygląda na to, że mogę:

  1. Użyj wiadomości, aby zmienić kod stanu (bleh)
  2. Lub utwórz moją wersję ChooseSuccessStatusCode i zgłoś wyjątek, który jest faktycznie użyteczny.
Kugel
źródło
1
Czy możesz pokazać fragment kodu?
Hamlet Hakobyan
1
Co rozumiesz przez „dostęp do tego kodu statusu”?
Marco
Pokaż kod, aby powiedzieć, gdzie otrzymujesz wyjątek.
duński
5
Chłopaki, co nie jest jasne w tytule tego pytania?
Kugel
1
Czy udało Ci się znaleźć jakieś właściwe rozwiązanie tego problemu? proszę o udostępnienie
Siddharth Pandey

Odpowiedzi:

37

Kod stanu został przekazany jako część ciągu do, HttpRequestExceptionwięc nie można go odzyskać tylko z takich wyjątków.

Projekt System.Net.Httpwymaga dostępu HttpResponseMessage.StatusCodezamiast czekania na wyjątek.

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

Jeśli teraz postępujesz zgodnie z instrukcjami firmy Microsoft , upewnij się, że dokładnie rozumiesz, dlaczego prosi Cię o telefon HttpResponseMessage.EnsureSucessStatusCode. Jeśli nie wywołasz tej funkcji, nie powinno być żadnych wyjątków.

Lex Li
źródło
2
Próbuję tutaj rozwiązać problem przekrojowy. Spójrz na moją zmianę, może jest lepsze rozwiązanie.
Kugel
1
Czy to pasuje do korzystania z HttpClient.GetStreamAsync (url), ponieważ nie widzę sposobu wykonania tej akcji bez konieczności usuwania tekstu wiadomości?
Senator
1
@TheSenator Musisz wywołać GetAsync (uri) lub PostAsync (uri), aby odzyskać HttpResponseMessage. Jeśli spróbujesz uzyskać treść odpowiedzi, czytając ją lub używając wygodnej metody, takiej jak GetStreamAsync, pod okapem wywoływana jest funkcja ZapewnijSuccessStatusCode.
odyth
6
To nasuwa oczywiste pytanie, jaki jest sens tego, że metody wygody są w ogóle dostępne, jeśli rzucają wyjątki, które nie pozwalają na użyteczne obsłużenie błędu. Zaśmiecanie kodu za pomocą instrukcji if i throw nie jest rozwiązaniem, więc z tego, co zostało tutaj powiedziane, wydaje się, że obecnie poprawną odpowiedzią jest to, że musisz ponownie zaimplementować albo metody wygody, albo samemu ZapewnićSuccessStatusCode.
Neutrino
1
Łatwiej powiedzieć niż zrobić. Wyjątek można zgłosić z kodu strony trzeciej. Na przykład automatycznie generowany klient Swagger.
user2555515
27

Na ile to warte, ten facet zrobił coś sprytnego: 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

W przypadku, gdy potrzebowałem właściwości statusu wyjątku, mogę to zrobić:

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

    return false;
}
Steve
źródło
14
głosowano w górę, ponieważ czasami nie masz dostępu do odpowiedzi, na przykład gdy byłeś zmuszony do korzystania z biblioteki, która opakowuje funkcjonalność i zgłasza wyjątki.
Kell
4
.net core 2.1 HttpClient ma GetAsync () i GetStreamAsync (). Pierwsza zwróci odpowiedź, podczas gdy druga wywoła wewnętrznie CompareSucessStatusCode i zgłosi HttpRequestException. Nie rozumiem tej niespójności i utrudnia obsługę błędów, ale doceniam to obejście.
smurtagh
2
Uruchomienie .NET Core 3.1.5 requestException.InnerExceptionjest zerowe, więc to nie zadziała
Ohad Schneider
3

Jak wspomnieli inni, nie jest dobrą praktyką pobieranie StatusCode z HttpRequestException, to samo można zrobić wcześniej z HttpResponseMessage.StatusCode po sprawdzeniu HttpResponseMessage.IsSuccessStatusCode

Tak czy inaczej, jeśli z powodu jakiegoś ograniczenia / wymagania trzeba czytać StatusCode, mogą być dwa rozwiązania

  1. Rozszerzono HttpResponseMessage o niestandardowy wyjątek wyjaśniony tutaj
  2. Hack na HttpRequestException.ToString, aby uzyskać StatusCode, ponieważ wiadomość jest stałym postem ustalonym przez StatusCode i Repharse.

Poniżej znajduje się kod w System.Net.Http.HttpResponseMessage Where SR.net_http_message_not_success_statuscode = "Kod stanu odpowiedzi nie wskazuje na sukces: {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;
    }
Surender Singh Malik
źródło
4
ciągi błędów o określonym formacie to zapach kodu, logika nigdy nie powinna na nich polegać.
user1496062
1
@ user1496062 Gdy błędy pochodzą z systemu zewnętrznego, często nie ma alternatywy.
Ian Warburton
1

To zadziałało dla mnie

var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
Rastislav Bodorik
źródło