Как получить 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)
Растислав Бодорик
источник