Як отримати код стану з HttpRequestException?


87

Мені, мабуть, тут не вистачає чогось очевидного.

Я використовую те, HttpClientщо кидає, HttpRequestExceptionщо міститься StatusCodeв рядку повідомлення.

Як я можу отримати доступ до цього StatusCode?


Редагувати : Докладніше, я написав це запитання поспіхом.

Я використовую HttpClientдля доступу до іншого API у своєму проекті WebApi. Так, я знаю, чому телефоную EnsureSuccessStatusCode(). Я хочу поширити деякі помилки нижче за течією, такі як 404 та 403.

Все, що я хотів, - це постійно перетворюватися HttpRequestExceptionна HttpResponseExceptionкористувальницькі ExceptionFilterAttribute.

На жаль, HttpRequestExceptionне містить додаткової інформації, яку я міг би використати крім повідомлення. Я сподівався розкрити StatusCodeв сирому (int або enum) вигляді.

Схоже, я можу:

  1. Використовуйте повідомлення для перемикання коду стану (bleh)
  2. Або створіть мою версію EnsureSuccessStatusCode і викиньте виняток, який насправді можна використовувати.

1
Чи можете ви показати шматок коду?
Гамлет Акопян

1
Що ви маєте на увазі під "доступом до цього коду стану"?
Марко

Покажіть код, повідомте, де ви отримуєте виняток.
данська

5
Хлопці, що незрозуміло в назві цього питання?
Kugel

1
Вам вдалося знайти якесь правильне рішення цієї проблеми? будь ласка, поділіться
Сіддхарт Панді

Відповіді:


37

Код стану передано як частину рядка, щоб HttpRequestExceptionви не могли відновити його лише за таких винятків.

Дизайн проекту System.Net.Httpвимагає доступу, HttpResponseMessage.StatusCodeа не очікування винятку.

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

Якщо ви зараз стежите за керівництвом Microsoft , переконайтеся, що добре розумієте, чому воно просить вас зателефонувати HttpResponseMessage.EnsureSucessStatusCode. Якщо ви не викликаєте цю функцію, не повинно бути винятків.


2
Тут я намагаюся вирішити наскрізну проблему. Подивіться на мою редакцію, можливо, є краще рішення.
Kugel

1
Чи підходить це з використанням HttpClient.GetStreamAsync (url), оскільки я не бачу способу виконання цієї дії без необхідності викреслювати текст повідомлення?
Сенатор

1
@TheSenator Вам потрібно зателефонувати GetAsync (uri) або PostAsync (uri), щоб повернути HttpResponseMessage. Якщо ви спробуєте отримати вміст відповіді, прочитавши його або використовуючи такий зручний метод, як GetStreamAsync, EnsureSuccessStatusCode викликається під капотом.
одіт

6
Що породжує очевидне питання, у чому сенс взагалі доступних методів зручності, якщо вони створюють винятки, які не дають можливості корисно обробляти помилку. Сміття коду операторами if і throw не є рішенням, тому з того, що було сказано тут, виявляється, що на даний момент правильною відповіддю є те, що вам доведеться самостійно застосувати або зручні методи, або EnsureSuccessStatusCode.
Нейтрино

1
Це простіше сказати, ніж зробити. Виняток може бути створений зі сторонніх кодів. Наприклад, автоматично сформований клієнт-шахрай.
user2555515

27

Наскільки це варте, цей хлопець зробив щось розумне: 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

У випадку, коли мені знадобилося властивість статусу винятку, я можу зробити це:

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

    return false;
}

14
проголосовано, бо іноді у вас немає доступу до відповіді, наприклад, коли вас змушують користуватися бібліотекою, яка обгортає функціонал і видає будь-які винятки.
Келл

4
.net core 2.1 HttpClient має GetAsync () та GetStreamAsync (). Перший поверне відповідь, тоді як інший викличе EnsureSucessStatusCode внутрішньо і видасть HttpRequestException. Я не розумію непослідовності, і це ускладнює обробку помилок, але я ціную цей обхідний шлях.
smurtagh

2
Запуск .NET Core 3.1.5 requestException.InnerExceptionє нульовим, тож це не буде працювати
Охад Шнайдер,

3

Як вже згадували інші, отримувати StatusCode з HttpRequestException не рекомендується, те ж саме можна зробити заздалегідь з HttpResponseMessage.StatusCode після перевірки HttpResponseMessage.IsSuccessStatusCode

У будь-якому випадку, якщо через якесь обмеження / вимогу потрібно прочитати StatusCode, рішення може бути два

  1. Розширено HttpResponseMessage з вашим спеціальним винятком, поясненим тут
  2. Зламайте HttpRequestException.ToString, щоб отримати StatusCode, оскільки повідомлення є постійним повідомленням, виправленим StatusCode і Repharse.

Нижче наведено код у System.Net.Http.HttpResponseMessage, де SR.net_http_message_not_success_statuscode = "Код стану відповіді не вказує на успіх: {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
Рядки помилок із певним форматом є запахом коду, логіка ніколи не повинна залежати від них.
user1496062

1
@ user1496062 Коли помилки надходять із зовнішньої системи, часто немає альтернативи.
Ian Warburton

1

Це спрацювало для мене

var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.