.NET HttpWebRequest.GetResponse () triggers Ausnahme aus, wenn HTTP-Statuscode 400 (ungültige Anforderung) zurückgegeben wird

Ich bin in einer Situation, in der, wenn ich einen HTTP 400-Code vom Server bekomme, es eine völlig legale Art und Weise ist, wie der Server mir sagt, was mit meiner Anfrage nicht stimmt (eine Nachricht im HTTP-Response-Inhalt verwendend)

Die .NET HttpWebRequest triggers jedoch eine Ausnahme aus, wenn der Statuscode 400 ist.

Wie gehe ich damit um? Für mich ist eine 400 völlig legal und ziemlich hilfreich. Der HTTP-Inhalt hat einige wichtige Informationen, aber die Ausnahme wirft mich von meinem Weg ab.

   

Es wäre schön, wenn es eine Möglichkeit gäbe, den “Nicht-Erfolg-Code” zu deaktivieren, aber wenn Sie WebException fangen, können Sie zumindest die Antwort verwenden:

using System; using System.IO; using System.Web; using System.Net; public class Test { static void Main() { WebRequest request = WebRequest.Create("http://csharpindepth.com/asd"); try { using (WebResponse response = request.GetResponse()) { Console.WriteLine("Won't get here"); } } catch (WebException e) { using (WebResponse response = e.Response) { HttpWebResponse httpResponse = (HttpWebResponse) response; Console.WriteLine("Error code: {0}", httpResponse.StatusCode); using (Stream data = response.GetResponseStream()) using (var reader = new StreamReader(data)) { string text = reader.ReadToEnd(); Console.WriteLine(text); } } } } } 

Vielleicht möchten Sie das Bit “Hol mir eine Antwort, auch wenn es kein Erfolgscode ist” in einer separaten Methode kapseln. (Ich würde vorschlagen, Sie casting immer noch, wenn es keine Antwort gibt, zB wenn Sie keine Verbindung herstellen konnten.)

Wenn die Fehlerreaktion groß sein kann (was ungewöhnlich ist), können Sie HttpWebRequest.DefaultMaximumErrorResponseLength optimieren, um sicherzustellen, dass Sie den gesamten Fehler erhalten.

Ich weiß, dass dies bereits vor langer Zeit beantwortet wurde, aber ich habe eine Erweiterungsmethode entwickelt, um hoffentlich anderen Menschen zu helfen, die zu dieser Frage kommen.

Code:

 public static class WebRequestExtensions { public static WebResponse GetResponseWithoutException(this WebRequest request) { if (request == null) { throw new ArgumentNullException("request"); } try { return request.GetResponse(); } catch (WebException e) { if (e.Response == null) { throw; } return e.Response; } } } 

Verwendung:

 var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com"); //... (initialize more fields) using (var response = (HttpWebResponse)request.GetResponseWithoutException()) { Console.WriteLine("I got Http Status Code: {0}", response.StatusCode); } 

Ich hatte ähnliche Probleme, als ich versuchte, eine Verbindung zum OAuth2-Dienst von Google herzustellen.

Ich habe den POST manuell geschrieben, nicht mit WebRequest, so:

 TcpClient client = new TcpClient("accounts.google.com", 443); Stream netStream = client.GetStream(); SslStream sslStream = new SslStream(netStream); sslStream.AuthenticateAsClient("accounts.google.com"); { byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToString()); StringBuilder msg = new StringBuilder(); msg.AppendLine("POST /o/oauth2/token HTTP/1.1"); msg.AppendLine("Host: accounts.google.com"); msg.AppendLine("Content-Type: application/x-www-form-urlencoded"); msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToString()); msg.AppendLine(""); Debug.WriteLine("Request"); Debug.WriteLine(msg.ToString()); Debug.WriteLine(content.ToString()); byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString()); sslStream.Write(headerAsBytes); sslStream.Write(contentAsBytes); } Debug.WriteLine("Response"); StreamReader reader = new StreamReader(sslStream); while (true) { // Print the response line by line to the debug stream for inspection. string line = reader.ReadLine(); if (line == null) break; Debug.WriteLine(line); } 

Die Antwort, die in den Antwortstream geschrieben wird, enthält den spezifischen Fehlertext, nach dem Sie suchen.

Mein Problem war insbesondere, dass ich Endpunkte zwischen url-kodierten Datenstücken setzte. Als ich sie rausnahm, funktionierte alles. Möglicherweise können Sie eine ähnliche Technik verwenden, um eine Verbindung zu Ihrem Dienst herzustellen und den tatsächlichen Antworterrorstext zu lesen.

Interessanterweise ist die HttpWebResponse.GetResponseStream() , die Sie von WebException.Response nicht mit dem Antwort-Stream identisch, den Sie vom Server erhalten hätten. In unserer Umgebung verlieren wir die tatsächlichen Serverantworten, wenn ein 400 HTTP-Statuscode mithilfe der HttpWebRequest/HttpWebResponse Objekte an den Client HttpWebRequest/HttpWebResponse . Aus dem, was wir gesehen haben, wird der Antwortstrom, der mit der WebException's HttpWebResponse ist, auf dem Client erzeugt und enthält keine Antwort des Body vom Server. Sehr frustrierend, da wir dem Kunden den Grund für die schlechte Anfrage mitteilen wollen.

Probieren Sie es aus (es ist VB-Code :-):

 Try Catch exp As WebException Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd End Try 

Eine asynchrone Version der Erweiterungsfunktion:

  public static async Task GetResponseAsyncNoEx(this WebRequest request) { try { return await request.GetResponseAsync(); } catch(WebException ex) { return ex.Response; } }