Как получить StatusCode из 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
Здесь я пытаюсь затронуть сквозную проблему. Посмотри на мою правку, может быть, есть лучшее решение.
— Кугель

1
Подходит ли это для использования HttpClient.GetStreamAsync (url), поскольку я не вижу способа выполнить это действие без необходимости вырезать текст сообщения?
— Сенатор

1
@TheSenator Вы должны вызвать GetAsync (uri) или PostAsync (uri), чтобы вернуть HttpResponseMessage. Если вы попытаетесь получить содержимое ответа, прочитав его или используя удобный метод, например GetStreamAsync, EnsureSuccessStatusCode вызывается изнутри.
— odyth 09

6
Возникает очевидный вопрос: зачем вообще нужны удобные методы, если они генерируют исключения, которые не позволяют с пользой обработать ошибку. Засорение вашего кода операторами if и throw не является решением, поэтому из того, что здесь было сказано, кажется, что в настоящее время правильный ответ заключается в том, что вам нужно переопределить либо вспомогательные методы, либо EnsureSuccessStatusCode самостоятельно.
— Neutrino

1
Легче сказать, чем сделать. Исключение может быть вызвано сторонним кодом. Например, автогенерированный клиент swagger.
— 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
проголосовали за, потому что иногда у вас нет доступа к ответу, например, когда вы вынуждены использовать библиотеку, которая обертывает функциональность и выдает любые исключения.
— Kell

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

2
Запуск .NET Core 3.1.5 requestException.InnerExceptionимеет значение null, поэтому это не сработает
— Охад Шнайдер,

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.