So erhalten Sie Fehlerinformationen, wenn HttpWebRequest.GetResponse () fehlschlägt

86

Ich initiiere eine HttpWebRequest und rufe dann deren Antwort ab. Gelegentlich erhalte ich einen Fehler von 500 (oder mindestens 5 ##), aber keine Beschreibung. Ich habe die Kontrolle über beide Endpunkte und möchte, dass das empfangende Ende ein bisschen mehr Informationen erhält. Zum Beispiel möchte ich die Ausnahmemeldung vom Server an den Client übergeben. Ist dies mit HttpWebRequest und HttpWebResponse möglich?

Code:

try
{
    HttpWebRequest webRequest = HttpWebRequest.Create(URL) as HttpWebRequest;
    webRequest.Method = WebRequestMethods.Http.Get;
    webRequest.Credentials = new NetworkCredential(Username, Password);
    webRequest.ContentType = "application/x-www-form-urlencoded";
    using(HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)
    {
        if(response.StatusCode == HttpStatusCode.OK)
        {
            // Do stuff with response.GetResponseStream();
        }
    }
}
catch(Exception ex)
{
    ShowError(ex);
    // if the server returns a 500 error than the webRequest.GetResponse() method
    // throws an exception and all I get is "The remote server returned an error: (500)."
}

Jede Hilfe dabei wäre sehr dankbar.

Trevor
quelle

Antworten:

150

Ist dies mit HttpWebRequest und HttpWebResponse möglich?

Sie könnten Ihren Webserver einfach den Ausnahmetext abfangen und in den Hauptteil der Antwort schreiben lassen und dann den Statuscode auf 500 setzen. Jetzt würde der Client eine Ausnahme auslösen, wenn ein 500-Fehler auftritt, aber Sie könnten den Antwortstrom lesen und den abrufen Meldung der Ausnahme.

Sie könnten also eine WebException abfangen, die ausgelöst wird, wenn ein Nicht-200-Statuscode vom Server zurückgegeben und dessen Text gelesen wird:

catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    using (var reader = new StreamReader(stream))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}
catch (Exception ex)
{
    // Something more serious happened
    // like for example you don't have network access
    // we cannot talk about a server exception here as
    // the server probably was never reached
}
Darin Dimitrov
quelle
Danke dir! Es ist wichtig zu beachten, dass der Stream innerhalb der using-Anweisung nicht außerhalb der using-Anweisung verfügbar ist, da der Disposer von WebResponse ihn löscht. Das hat mich ein paar Minuten lang gestolpert.
Thorin
@ Thorin. Der "Stream" von der ersten Anweisung wird zur nächsten Anweisung weitergeleitet. Genau wie in einer einzeiligen IF-Anweisung, zum Beispiel wenn (etwas) hier etwas tut;
RealityDysfunction
1
GetRequestStreamund GetResponsekann Ausnahmen werfen ?
PreguntonCojoneroCabrón
@ PreguntonCojoneroCabrón Ja, es scheint nicht ganz richtig zu sein, oder? Zum Glück hat Microsoft die HttpClient-Klasse eingeführt, die vermutlich die meisten heutzutage verwenden. msdn.microsoft.com/en-us/library/…
Morten Nørgaard
8

Ich bin auf diese Frage gestoßen, als ich versucht habe zu überprüfen, ob eine Datei auf einer FTP-Site vorhanden ist oder nicht. Wenn die Datei nicht vorhanden ist, tritt beim Überprüfen des Zeitstempels ein Fehler auf. Aber ich möchte sicherstellen, dass der Fehler nichts anderes ist, indem ich seinen Typ überprüfe.

Die ResponseEigenschaft on WebExceptionist vom Typ, FtpWebResponsefür den Sie ihre StatusCodeEigenschaft überprüfen können, um festzustellen, welcher FTP-Fehler vorliegt Sie haben.

Hier ist der Code, mit dem ich gelandet bin:

    public static bool FileExists(string host, string username, string password, string filename)
    {
        // create FTP request
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + host + "/" + filename);
        request.Credentials = new NetworkCredential(username, password);

        // we want to get date stamp - to see if the file exists
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        try
        {
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            var lastModified = response.LastModified;

            // if we get the last modified date then the file exists
            return true;
        }
        catch (WebException ex)
        {
            var ftpResponse = (FtpWebResponse)ex.Response;

            // if the status code is 'file unavailable' then the file doesn't exist
            // may be different depending upon FTP server software
            if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                return false;
            }

            // some other error - like maybe internet is down
            throw;
        }
    }
Simon_Weaver
quelle
3

Ich sah mich einer ähnlichen Situation gegenüber:

Ich habe versucht, die Raw-Antwort im Falle eines HTTP-Fehlers zu lesen, der einen SOAP-Dienst mithilfe von BasicHTTPBinding verbraucht.

Beim Lesen der Antwort mit GetResponseStream()wurde jedoch der Fehler angezeigt:

Stream nicht lesbar

Also, dieser Code hat bei mir funktioniert:

try
{
    response = basicHTTPBindingClient.CallOperation(request);
}
catch (ProtocolException exception)
{
    var webException = exception.InnerException as WebException;
    var rawResponse = string.Empty;

    var alreadyClosedStream = webException.Response.GetResponseStream() as MemoryStream;
    using (var brandNewStream = new MemoryStream(alreadyClosedStream.ToArray()))
    using (var reader = new StreamReader(brandNewStream))
        rawResponse = reader.ReadToEnd();
}
João Paulo Melo
quelle
0

Sie können diese Bibliothek auch verwenden die HttpWebRequest und Response in einfache Methoden umschließt, die Objekte basierend auf den Ergebnissen zurückgeben. Es verwendet einige der in diesen Antworten beschriebenen Techniken und verfügt über reichlich Code, der von Antworten aus diesem und ähnlichen Themen inspiriert ist. Es fängt automatisch alle Ausnahmen ab, versucht so viel Kesselplattencode wie möglich zu abstrahieren, um diese Webanforderungen zu stellen, und deserialisiert das Antwortobjekt automatisch.

Ein Beispiel dafür, wie Ihr Code mit diesem Wrapper aussehen würde, ist so einfach wie

    var response = httpClient.Get<SomeResponseObject>(request);
    
    if(response.StatusCode == HttpStatusCode.OK)
    {
        //do something with the response
        console.Writeline(response.Body.Id); //where the body param matches the object you pass in as an anonymous type.  
    }else {
         //do something with the error
         console.Writelint(string.Format("{0}: {1}", response.StatusCode.ToString(), response.ErrorMessage);

    }

Vollständige Offenlegung Diese Bibliothek ist eine kostenlose Open-Source-Wrapper-Bibliothek, und ich bin der Autor dieser Bibliothek. Ich verdiene kein Geld damit, habe es aber im Laufe der Jahre als äußerst nützlich empfunden und bin mir sicher, dass jeder, der noch die Klassen HttpWebRequest / HttpWebResponse verwendet, dies auch tun wird.

Es ist kein Patentrezept, unterstützt jedoch das Abrufen, Veröffentlichen, Löschen mit asynchronem und nicht asynchronem Abrufen und Veröffentlichen sowie JSON- oder XML-Anforderungen und -Antworten. Es wird ab dem 21.06.2020 aktiv gepflegt

pat8719
quelle
-3
HttpWebRequest myHttprequest = null;
HttpWebResponse myHttpresponse = null;
myHttpRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpRequest.Method = "POST";
myHttpRequest.ContentType = "application/x-www-form-urlencoded";
myHttpRequest.ContentLength = urinfo.Length;
StreamWriter writer = new StreamWriter(myHttprequest.GetRequestStream());
writer.Write(urinfo);
writer.Close();
myHttpresponse = (HttpWebResponse)myHttpRequest.GetResponse();
if (myHttpresponse.StatusCode == HttpStatusCode.OK)
 {
   //Perform necessary action based on response
 }
myHttpresponse.Close(); 
Pranesh Janarthanan
quelle