Kod stanu HTTP System.Net.WebException

Odpowiedzi:

248

Może coś takiego ...

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
    }
}
LukeH
źródło
ale w przypadku wyjątku „connectfailure” wyjątku internetowego otrzymuję odpowiedź jako zerową, w takim przypadku jak mogę uzyskać kod httpstatus
Rusty
8
@rusty: Nie możesz. Jeśli wystąpi błąd połączenia, nie ma kodu stanu HTTP do pobrania.
LukeH
4
Jeśli błąd jest protokołem ProtocolError, nie musisz sprawdzać odpowiedzi pod kątem wartości null. Zobacz komentarz w przykładzie na tej stronie MSDN
Andras Toth
5
@AndrasToth Ale narzędzia takie jak ReSharper dadzą ci ostrzeżenie, jeśli pominiesz sprawdzenie null. W każdym razie dobrą praktyką jest programowanie defensywne.
Tom Lint
1
Jak uzyskać wartość HTTP Substatus ? Na przykład 404.13 Zbyt duża długość zawartości : docs.microsoft.com/en-us/iis/configuration/system.webServer/ ...
Kiquenet
27

Używając operatora warunkowego zerowego ( ?.), możesz uzyskać kod stanu HTTP za pomocą jednej linii kodu:

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

Zmienna statusbędzie zawierać HttpStatusCode. Gdy wystąpi bardziej ogólna awaria, taka jak błąd sieciowy, w którym nie jest wysyłany żaden kod statusu HTTP, wówczas statusbędzie miał wartość NULL. W takim przypadku można sprawdzić ex.Status, aby uzyskać WebExceptionStatus.

Jeśli chcesz, aby opisowy ciąg był rejestrowany w przypadku niepowodzenia, możesz użyć operatora łączenia wartości null ( ??), aby uzyskać odpowiedni błąd:

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

Jeśli wyjątek zostanie zgłoszony w wyniku kodu stanu HTTP 404, ciąg znaków będzie zawierał „NotFound”. Z drugiej strony, jeśli serwer jest offline, ciąg będzie zawierał „ConnectFailure” i tak dalej.

(I dla każdego, kto chce wiedzieć, jak uzyskać kod podstatusu HTTP. To nie jest możliwe. Jest to koncepcja Microsoft IIS, która jest logowana tylko na serwerze i nigdy nie jest wysyłana do klienta).

Martin Liversage
źródło
Nie jestem pewien, czy ?.operator został pierwotnie nazwany operatorem propagacji wartości null, czy operatorem warunkowym o wartości null podczas wersji zapoznawczej. Jednak Atlassian resharper ostrzega przed użyciem operatora propagacji wartości null w takich scenariuszach. Dobrze wiedzieć, że jest również nazywany operatorem warunkowym zerowym.
RBT
1
Trochę za późno na tę imprezę, ale uczciwe ostrzeżenie, że operator warunkowy zerowy jest funkcją C # 6.0, więc trzeba użyć kompilatora, który go obsługuje. Odpowiedź przepełnienia stosu z dalszymi szczegółami . VS 2015+ ma to domyślnie, ale jeśli ktoś używa innego rodzaju środowiska budowania / wdrażania niż tylko „ich komputer”, może być konieczne wzięcie pod uwagę innych rzeczy.
CodeHxr
9

działa to tylko wtedy, gdy WebResponse jest 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;
}
pr0gg3r
źródło
dlaczego zajmować się tylko 401-Unauthorized zamiast wszystkimi możliwymi kodami błędów HTTP? to jest najgorsza odpowiedź
ympostor
4
@ympostor To jest tylko przykład. Każdy rozsądny programista to rozumie. Twój komentarz jest najbardziej bezmyślny, jaki tu czytałem.
pr0gg3r
9

(Zdaję sobie sprawę, że pytanie jest stare, ale jest jednym z najpopularniejszych w Google).

Typowa sytuacja, w której chcesz poznać kod odpowiedzi, dotyczy obsługi wyjątków. Począwszy od C # 7, możesz użyć dopasowania do wzorca, aby faktycznie wprowadzić klauzulę catch tylko wtedy, gdy wyjątek pasuje do twojego predykatu:

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

Można to łatwo rozszerzyć na dalsze poziomy, na przykład w tym przypadku, gdy WebExceptionfaktycznie był wewnętrznym wyjątkiem innego (i tylko nas interesuje 404):

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

Na koniec: zwróć uwagę, że nie ma potrzeby ponownego zgłaszania wyjątku w klauzuli catch, gdy nie pasuje on do twoich kryteriów, ponieważ nie wprowadzamy klauzuli na pierwszym miejscu w powyższym rozwiązaniu.

miniyou
źródło
4

Możesz wypróbować ten kod, aby uzyskać kod stanu HTTP z WebException. Działa również w Silverlight, ponieważ SL nie ma zdefiniowanego WebExceptionStatus.ProtocolError.

HttpStatusCode GetHttpStatusCode(WebException we)
{
    if (we.Response is HttpWebResponse)
    {
        HttpWebResponse response = (HttpWebResponse)we.Response;
        return response.StatusCode;
    }
    return null;
}
Siergiej
źródło
1
return 0? lub lepiej HttpStatusCode?( null )?
Kiquenet
Czy to zadziała? var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}
FMFF
Nie rozumiem, co chciałeś zrobić w tej próbce. W jakich przypadkach chciałeś, aby zdarzenie było rejestrowane?
Siergiej
1

Nie jestem pewien, czy istnieje, ale gdyby istniała taka nieruchomość, nie zostałaby uznana za wiarygodną. WebExceptionMoże być zwolniony z przyczyn innych niż HTTP Kody błędów w tym prostych błędów sieciowych. Te nie mają takiego pasującego kodu błędu http.

Czy możesz nam podać więcej informacji na temat tego, co próbujesz osiągnąć za pomocą tego kodu. Może istnieć lepszy sposób na uzyskanie potrzebnych informacji.

JaredPar
źródło