System.Net.WebException HTTP-Statuscode


Antworten:


248

Vielleicht so etwas ...

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
    }
}

aber im Falle einer "connectfailure" -Ausnahme von webexception erhalte ich eine Antwort als null. In diesem Fall, wie kann ich den httpstatus-Code erhalten
Rusty

8
@rusty: Das kannst du nicht. Wenn ein Verbindungsfehler auftritt, muss kein HTTP-Statuscode abgerufen werden.
LukeH

4
Wenn der Fehler ein ProtocolError ist, müssen Sie die Antwort nicht auf null überprüfen. Siehe den Kommentar im Beispiel auf dieser MSDN-Seite
Andras Toth

5
@AndrasToth Tools wie ReSharper geben jedoch eine Warnung aus, wenn Sie die Nullprüfung weglassen. In jedem Fall empfiehlt es sich, defensiv zu codieren.
Tom Lint

1
Wie erhalte ich den HTTP-Substatus- Wert? Beispiel : 404.13
Inhaltslänge

27

Mit dem nullbedingten Operator ( ?.) können Sie den HTTP-Statuscode mit einer einzigen Codezeile abrufen:

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

Die Variable statusenthält die HttpStatusCode. Wenn ein allgemeinerer Fehler wie ein Netzwerkfehler auftritt, bei dem niemals ein HTTP-Statuscode gesendet statuswird, ist dieser Wert null. In diesem Fall können Sie überprüfen ex.Status, um die zu erhalten WebExceptionStatus.

Wenn Sie nur möchten, dass eine beschreibende Zeichenfolge im Falle eines Fehlers protokolliert wird, können Sie den Null-Coalescing-Operator ( ??) verwenden, um den entsprechenden Fehler abzurufen:

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

Wenn die Ausnahme aufgrund eines 404-HTTP-Statuscodes ausgelöst wird, enthält die Zeichenfolge "NotFound". Wenn der Server hingegen offline ist, enthält die Zeichenfolge "ConnectFailure" usw.

(Und für alle, die wissen möchten, wie sie den HTTP-Subcode erhalten. Dies ist nicht möglich. Es handelt sich um ein Microsoft IIS-Konzept, das nur auf dem Server protokolliert und nie an den Client gesendet wird.)


Nicht sicher, ob der ?.Operator während der Vorschau-Freigabe ursprünglich als Null-Propagierungsoperator oder als Null-Bedingungsoperator bezeichnet wurde. Atlassian resharper warnt jedoch davor, in solchen Szenarien den Null-Propagierungsoperator zu verwenden. Gut zu wissen, dass es auch als nullbedingter Operator bezeichnet wird.
RBT

1
Ein bisschen spät zu dieser Party, aber faire Warnung, dass der nullbedingte Operator eine C # 6.0-Funktion ist, daher muss ein Compiler verwendet werden, der dies unterstützt. Antwort auf Stapelüberlauf mit weiteren Details . VS 2015+ hat es standardmäßig, aber wenn man eine andere Build / Deployment-Umgebung als nur "ihren Computer" verwendet, müssen möglicherweise andere Dinge berücksichtigt werden.
CodeHxr

9

Dies funktioniert nur, wenn WebResponse eine HttpWebResponse ist.

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;
}

Warum nur mit 401-Unauthorized statt mit allen möglichen HTTP-Fehlerstatuscodes umgehen? Dies ist die schlechteste Antwort
ympostor

4
@ympostor Dies ist nur ein Beispiel. Jeder vernünftige Entwickler versteht dies. Ihr Kommentar ist der gedankenloseste, den ich je hier gelesen habe.
pr0gg3r

9

(Mir ist klar, dass die Frage alt ist, aber sie gehört zu den Top-Hits bei Google.)

Eine häufige Situation, in der Sie den Antwortcode wissen möchten, ist die Ausnahmebehandlung. Ab C # 7 können Sie den Mustervergleich verwenden, um die catch-Klausel nur dann einzugeben, wenn die Ausnahme mit Ihrem Prädikat übereinstimmt:

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

Dies kann leicht auf weitere Ebenen erweitert werden, wie in diesem Fall, in dem dies WebExceptiontatsächlich die innere Ausnahme eines anderen war (und wir nur daran interessiert sind 404):

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

Zum Schluss: Beachten Sie, dass die Ausnahme in der catch-Klausel nicht erneut ausgelöst werden muss, wenn sie nicht Ihren Kriterien entspricht, da wir die Klausel mit der obigen Lösung erst gar nicht eingeben.


4

Sie können diesen Code ausprobieren, um HTTP-Statuscode von WebException abzurufen. Es funktioniert auch in Silverlight, da in SL WebExceptionStatus.ProtocolError nicht definiert ist.

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

1
return 0? oder besser HttpStatusCode?( nullbar )?
Kiquenet

Ob das funktioniert? var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}
FMFF

Ich kann nicht verstehen, was Sie in diesem Beispiel tun wollten. In welchen Fällen sollte das Ereignis protokolliert werden?
Sergey

1

Ich bin mir nicht sicher, ob es eine gibt, aber wenn es eine solche Eigenschaft gäbe, würde sie nicht als zuverlässig angesehen werden. A WebExceptionkann aus anderen Gründen als HTTP-Fehlercodes einschließlich einfacher Netzwerkfehler ausgelöst werden. Diese haben keinen solchen passenden http-Fehlercode.

Können Sie uns etwas mehr Informationen darüber geben, was Sie mit diesem Code erreichen möchten? Möglicherweise gibt es einen besseren Weg, um die benötigten Informationen zu erhalten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.