Wie kann ich eine 404 fangen?

93

Ich habe folgenden Code:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";
request.Credentials = MyCredentialCache;

try
{
    request.GetResponse();
}
catch
{
}

Wie kann ich einen bestimmten 404-Fehler abfangen? Der WebExceptionStatus.ProtocolError kann nur erkennen, dass ein Fehler aufgetreten ist, gibt jedoch nicht den genauen Code des Fehlers an.

Beispielsweise:

catch (WebException ex)
{
    if (ex.Status != WebExceptionStatus.ProtocolError)
    {
        throw ex;
    }
}

Ist einfach nicht nützlich genug ... die Protokollausnahme könnte 401, 503, 403 sein, eigentlich alles.

J L.
quelle
13
NNNOOOOOOOOOOOOOO! Fangen Sie nicht System.Exceptionund hängen Sie nicht vom Ausnahmetext in Ihrem Handler ab!
Aaronaught
2
John Saunders Antwort war die vollständigste. Ich denke, die Leute haben ihn nur aus Trotz herabgestimmt.
Aaronaught
3
Nicht verwenden throw ex, Sie generieren eine neue Ausnahme mit einem leeren Aufrufstapel. Einfach benutzen throw.
krbnr
1
Ich fand das selbst immer frustrierend. Eine Ausnahme sollte nicht ausgelöst werden, wenn Sie eine wohlgeformte Antwort erhalten und eine Protokollfehlermeldung definitiv wohlgeformt ist. Die Klasse sollte es dem Benutzer ermöglichen, die Ergebnisse zu interpretieren und entsprechend zu handeln.
Jeremy Holovacs
@ JeremyHolovacs Ausnahmen werden für Dinge wie 404 in neueren http-Clients nicht mehr ausgelöst. "Verwenden Sie keine Ausnahmen für den Kontrollfluss" schien das Team, das gebaut hat, nicht zu überlebenWebRequest
Matt Kocaj

Antworten:

113

Verwenden Sie die HttpStatusCode Enumeration, speziellHttpStatusCode.NotFound

Etwas wie:

HttpWebResponse errorResponse = we.Response as HttpWebResponse;
if (errorResponse.StatusCode == HttpStatusCode.NotFound) {
  //
}

Wo
weist ein WebException.

Jay Riggs
quelle
Kann ich die NUMMER irgendwie aus den Objekten herausholen, ohne meine eigene Suchliste zu erstellen? Ich hätte gerne etwas wie: int httpresponsecode = HttpStatusCode.ToInt () oder ähnliches, damit ich 404
BerggreenDK
2
@BerggreenDK Sie sollten in der Lage sein, nur int httpresonsecode = (int) HttpStatusCode.NotFound
Trev
7
-1 Teilweise Erklärung meiner alten Ablehnung: Code löst eine NullReferenceException aus, wenn dies aus irgendeinem Grund we.Responsenicht der Fall ist HttpWebResponse. Wenn der Code davon ausgehen möchte, dass er immer diesen Typ hat, sollte er einfach Folgendes umwandeln : HttpWebResponse errorResponse = (HttpWebResponse)we.Response;. Dies wird eine explizite, InvalidCastExceptionwenn das Unmögliche passiert, anstelle einer mysteriösen werfen NullReferenceException.
John Saunders
Ich An object reference is required for the non-static field, method, or property 'WebException.Response'benutze diesen Code.
Jamie
122
try
{
    var request = WebRequest.Create(uri);
    using (var response = request.GetResponse())
    {
        using (var responseStream = response.GetResponseStream())
        {
            // Process the stream
        }
    }
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError &&
        ex.Response != null)
    {
        var resp = (HttpWebResponse) ex.Response;
        if (resp.StatusCode == HttpStatusCode.NotFound)
        {
            // Do something
        }
        else
        {
            // Do something else
        }
    }
    else
    {
        // Do something else
    }
}
John Saunders
quelle
10
lol @ ist die IDisposable-Polizei und gibt jedem eine -1, wenn er die Antwort nicht in einen using-Block einwickelt.
Rich
2
Es ist ein harter Job, aber jemand muss es tun. OTOH, ich habe diese Antwort fast nicht hinzugefügt, da es den Anschein hat, als würde ich alle anderen dazu bringen, meine Antwort zur am besten bewerteten zu machen.
John Saunders
3
Ich habe tatsächlich gestimmt, aber ich habe nur eines bemerkt: Es sollte wahrscheinlich ein throw(Umwerfen) am Ende von dir geben catch, sonst wird dies nur stillschweigend jede andere Art von essen WebException.
Aaronaught
@ John Saunders: Warum können Sie Ihre Anfrage nicht auch verwenden?
Joel Etherton
1
@ Joel: WebRequestnicht implementiert IDisposable.
John Saunders
23

In C # 6 können Sie Ausnahmefilter verwenden .

try
{
    var request = WebRequest.Create(uri);
    using (var response = request.GetResponse())
    using (var responseStream = response.GetResponseStream())
    {
        // Process the stream
    }
}
catch(WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound)
{
    // handle 404 exceptions
}
catch (WebException ex)
{
    // handle other web exceptions
}
Handwerksspiele
quelle
Eine sehr coole Funktion, die ich übersehen habe! Ich suchte immer wieder nach Methoden, um nur 401 zu fangen, während andere an den allgemeinen Ausnahmebehandler weitergeleitet wurden. Dies ist der richtige Weg!
Lionet Chen
12

Ich habe das nicht getestet, aber es sollte funktionieren

try
{
    // TODO: Make request.
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError) {
        HttpWebResponse resp = ex.Response as HttpWebResponse;
        if (resp != null && resp.StatusCode == HttpStatusCode.NotFound)
        {
            // TODO: Handle 404 error.
        }
        else
            throw;
    }
    else
        throw;
}
MiffTheFox
quelle
@ John Saunders - Ich habe den Code des OP angepasst und nicht optimiert.
MiffTheFox
@ John - Und vielleicht hatte ich nur erwartet, dass sie den catchBlock kopieren / einfügen , da ich beim Versuch genau den gleichen Code hatte wie das OP. Sie sollten diese Frage dann aufgrund des OP-Codes wirklich ganz ablehnen.
MiffTheFox
1
@ John wir vergessen hier ist Beispielcode. Dies ist der Fall, es ist ein anderer Weg zu 404, nicht wie GetResponse verwendet wird. -1 scheint ein wenig hart zu sein. +1 an Miff für die Beantwortung der Frage.
David Basarab
@ John Ich finde es gut, dass Sie in einem Kommentar darauf hinweisen. Ich sehe Abstimmungen so, wenn der angegebene Code das Problem nicht löst. Vielen Dank, dass Sie die Abwahl entfernt haben.
David Basarab
@ John - Gut, ich habe alles außer dem Fang losgeworden, jetzt glücklich?
MiffTheFox
4

Ich denke, wenn Sie eine WebException abfangen, gibt es dort einige Informationen, anhand derer Sie feststellen können, ob es sich um eine 404 handelt. Nur so kenne ich sie derzeit ... Ich wäre daran interessiert, andere zu kennen ...

catch(WebException e) {
    if(e.Status == WebExceptionStatus.ProtocolError) {
        var statusCode = (HttpWebResponse)e.Response).StatusCode);
        var description = (HttpWebResponse)e.Response).StatusDescription);
    }
}
Mezoid
quelle
2

Schauen Sie sich diesen Snipit an. Die GetResponse löst eine WebRequestException aus. Wenn Sie das abfangen, erhalten Sie den Statuscode aus der Antwort.

try {
   // Create a web request for an invalid site. Substitute the "invalid site" strong in the Create call with a invalid name.
     HttpWebRequest myHttpWebRequest = (HttpWebRequest) WebRequest.Create("invalid site");

    // Get the associated response for the above request.
     HttpWebResponse myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse();
    myHttpWebResponse.Close();
}
catch(WebException e) {
    Console.WriteLine("This program is expected to throw WebException on successful run."+
                        "\n\nException Message :" + e.Message);
    if(e.Status == WebExceptionStatus.ProtocolError) {
        Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
        Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
    }
}
catch(Exception e) {
    Console.WriteLine(e.Message);
}

Dies kam von http://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspx

Jonathan S.
quelle
2

Fangen Sie den richtigen Ausnahmetyp ab WebException:

try
{
    var request = (HttpWebRequest) WebRequest.Create(String.Format("http://www.gravatar.com/avatar/{0}?d=404", hashe));

    using(var response = (HttpWebResponse)request.GetResponse())
        Response.Write("has avatar");
}
catch(WebException e) 
{
  if(e.Response.StatusCode == 404) 
    Response.Write("No avatar");
}
Nick Craver
quelle
@ John Saunders Ich diskutiere Sie dort nicht, aber das war nicht die Frage, er fragte nach dem besten Weg, einen 404 zu erfassen. Meine Änderungen an seinem Code beschränkten sich auf die Beantwortung der Frage, um die Änderung so einfach und offensichtlich wie möglich zu machen möglich.
Nick Craver
@ John Saunders: Behoben, ich nehme an, "wenn dies am effizientesten ist" lässt es auf die Frage zutreffen.
Nick Craver
Musste nur das e.Responsewie HttpWebResponsevorher besetzen, um Zugang zum zu bekommen StatusCode.
Lankymart
2

Informationen zum Status der Antwort finden Sie bei MSDN :

...
catch(WebException e) {
  Console.WriteLine("The following error occured : {0}",e.Status);  
}
...
Dror
quelle
2
@ John Saunders - Ich werde es gerne an MSDN weitergeben (wo ich das Beispiel von ... kopiert habe). Der Zweck dieses Codes ist es, die Verwendung von StatusCode zu zeigen, nicht so effizient wie möglich zu sein.
Dror
2
@ John Saunders - Ich habe nur den Teil verlassen, den ich zeigen wollte, Nur für dich :-)
Dror
2

Ich glaube, für VB.NET-Leute, die dies durchsuchen, können wir die Ausnahme nur dann abfangen, wenn es sich wirklich um eine 404 handelt.

Try
    httpWebrequest.GetResponse()
Catch we As WebException When we.Response IsNot Nothing _
                              AndAlso TypeOf we.Response Is HttpWebResponse _
                              AndAlso (DirectCast(we.Response, HttpWebResponse).StatusCode = HttpStatusCode.NotFound)

    ' ...

End Try
unbekannt
quelle
1

Wenn POST- oder GET-Daten mithilfe der WebRequest-Klasse an den Server gesendet werden, lautet der Ausnahmetyp WebException. Nachfolgend finden Sie den Code für die Ausnahme "Datei nicht gefunden"

        //Create a web request with the specified URL
            string path = @"http://localhost/test.xml1";
            WebRequest myWebRequest = WebRequest.Create(path);

       //Senda a web request and wait for response.
                try
                {
                    WebResponse objwebResponse = myWebRequest.GetResponse();
                    Stream stream= objwebResponse.GetResponseStream();

                }
                catch (WebException ex) {
                    if (((HttpWebResponse)(ex.Response)).StatusCode == HttpStatusCode.NotFound) {
                        throw new FileNotFoundException(ex.Message);
                    }

                }
Sheo Dayal Singh
quelle