System.Net.WebException HTTP код состояния


Ответы:


248

Может быть как то так ...

try
{
    // ...
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError)
    {
        var response = ex.Response as HttpWebResponse;
        if (response != null)
        {
            Console.WriteLine("HTTP Status Code: " + (int)response.StatusCode);
        }
        else
        {
            // no http status code available
        }
    }
    else
    {
        // no http status code available
    }
}

но в случае исключения "connectfailure" из webexception я получаю ответ как ноль, в таком случае как я могу получить код httpstatus
Rusty

8
@rusty: ты не можешь. Если произошел сбой соединения, то получить код состояния HTTP невозможно.
LukeH

4
Если ошибка - ProtocolError, вам не нужно проверять ответ на null. Смотрите комментарий в примере на этой странице MSDN
Андрас Тот

5
@AndrasToth Но такие инструменты, как ReSharper, будут предупреждать вас, если вы пропустите нулевую проверку. И в любом случае, это хорошая практика для защиты кода.
Том Линт

1
Как получить значение HTTP Substatus ? Например, 404.13 Длина содержимого слишком велика
Kiquenet,

27

Используя нулевой условный оператор ( ?.), вы можете получить код состояния HTTP с одной строкой кода:

 HttpStatusCode? status = (ex.Response as HttpWebResponse)?.StatusCode;

Переменная statusбудет содержать HttpStatusCode. Когда происходит более общий сбой, такой как ошибка сети, когда код состояния HTTP никогда не отправляется, то statusон будет нулевым. В этом случае вы можете проверить, ex.Statusчтобы получить WebExceptionStatus.

Если вы просто хотите, чтобы описательная строка регистрировалась в случае сбоя, вы можете использовать оператор null-coalescing ( ??), чтобы получить соответствующую ошибку:

string status = (ex.Response as HttpWebResponse)?.StatusCode.ToString()
    ?? ex.Status.ToString();

Если исключение выдается в результате кода состояния HTTP 404, строка будет содержать «NotFound». С другой стороны, если сервер находится в автономном режиме, строка будет содержать «ConnectFailure» и так далее.

(И для любого, кто хочет знать, как получить код подстатуса HTTP. Это невозможно. Это концепция Microsoft IIS, которая регистрируется только на сервере и никогда не отправляется клиенту.)


Не уверен, был ли ?.оператор первоначально назван нулевым оператором распространения или нулевым условным оператором во время предварительного просмотра. Но Atlassian Resharper предупреждает об использовании нулевого оператора распространения в таких сценариях. Приятно знать, что его еще называют нулевым условным оператором.
RBT

1
Немного опоздал на эту вечеринку, но справедливое предупреждение о том, что нулевой условный оператор является функцией C # 6.0, поэтому нужно использовать компилятор, который его поддерживает. Ответ переполнения стека с более подробной информацией . VS 2015+ имеет его по умолчанию, но если кто-то использует какую-либо среду сборки / развертывания, отличную от «своей машины», возможно, следует принять во внимание и другие вещи.
CodeHxr

9

это работает, только если WebResponse является HttpWebResponse.

try
{
    ...
}
catch (System.Net.WebException exc)
{
    var webResponse = exc.Response as System.Net.HttpWebResponse;
    if (webResponse != null && 
        webResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized)
    {
        MessageBox.Show("401");
    }
    else
        throw;
}

почему работают только с 401-Unauthorized вместо всех возможных кодов ошибок HTTP? это худший ответ
ympostor

4
@ympostor Это всего лишь пример. Любой разумный разработчик это понимает. Ваш комментарий - самый бездумный, который я когда-либо читал здесь.
pr0gg3r

9

(Я понимаю, что вопрос старый, но он входит в число самых популярных в Google.)

Распространенной ситуацией, когда вы хотите знать код ответа, является обработка исключений. Начиная с C # 7, вы можете использовать сопоставление с образцом для фактического ввода предложения catch, только если исключение соответствует вашему предикату:

catch (WebException ex) when (ex.Response is HttpWebResponse response)
{
     doSomething(response.StatusCode)
}

Это может быть легко расширено до следующих уровней, например, в этом случае, где WebExceptionфактически было внутреннее исключение другого (и мы заинтересованы только в этом 404):

catch (StorageException ex) when (ex.InnerException is WebException wex && wex.Response is HttpWebResponse r && r.StatusCode == HttpStatusCode.NotFound)

Напоследок: обратите внимание, что нет необходимости повторно генерировать исключение в предложении catch, если оно не соответствует вашим критериям, поскольку мы не вводим это предложение в первую очередь с помощью вышеуказанного решения.


4

Вы можете попробовать этот код, чтобы получить код состояния HTTP из WebException. Он также работает в Silverlight, поскольку SL не имеет определенного WebExceptionStatus.ProtocolError.

HttpStatusCode GetHttpStatusCode(WebException we)
{
    if (we.Response is HttpWebResponse)
    {
        HttpWebResponse response = (HttpWebResponse)we.Response;
        return response.StatusCode;
    }
    return null;
}

1
return 0? или лучше HttpStatusCode?( обнуляемый )?
Kiquenet

Будет ли это работать? var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}
FMFF

Я не могу понять, что вы хотели сделать в этом примере. В каких случаях вы хотели, чтобы событие было зарегистрировано?
Сергей

1

Я не уверен, что есть, но если бы была такая собственность, она не была бы признана надежной. A WebExceptionможет быть запущено по причинам, отличным от кодов ошибок HTTP, включая простые сетевые ошибки. У тех нет такого совпадающего кода ошибки http.

Можете ли вы дать нам немного больше информации о том, что вы пытаетесь достичь с помощью этого кода. Там может быть лучший способ получить необходимую информацию.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.