.Net HttpWebRequest.GetResponse () wirft Ausnahme, wenn HTTP-Statuscode 400 (bad request) zurückgegeben

StackOverflow https://stackoverflow.com/questions/692342

  •  22-08-2019
  •  | 
  •  

Frage

Ich bin in einer Situation, wo, wenn ich eine HTTP 400-Fehlercode vom Server erhalte, ist es eine völlig legale Art und Weise des Servers ist mir zu sagen, was mit meiner Anfrage falsch war (eine Nachricht in dem HTTP-Antwort-Gehalt verwendet wird)

Allerdings ist die .NET HttpWebRequest löst eine Ausnahme aus, wenn der Statuscode 400

Wie gehe ich das? Für mich ist ein 400 völlig legal und ziemlich hilfreich. Der HTTP-Content hat einige wichtige Informationen, sondern die Ausnahme wirft mich aus meinem Weg.

War es hilfreich?

Lösung

Es wäre schön, wenn es eine Möglichkeit, ist das Abschaltens „wirft auf Nicht-Erfolgscode“ aber wenn Sie fangen WebException Sie zumindest die Antwort verwenden können:

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

Sie können gerne die einzukapseln „mir eine Antwort erhalten, auch wenn es kein Erfolgscode ist“ Bit in einem separaten Verfahren. (Ich würde Sie noch vorschlagen werfen, wenn es nicht eine Antwort, zum Beispiel, wenn Sie keine Verbindung herstellen können.)

Wenn die Fehlerreaktion groß sein kann (was ungewöhnlich ist) Sie a href zwicken möchten <= „https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.defaultmaximumerrorresponselength“ rel = "noreferrer"> HttpWebRequest.DefaultMaximumErrorResponseLength um sicherzustellen, dass Sie den gesamten Fehler.

Andere Tipps

Ich weiß, das hat schon vor langer Zeit beantwortet worden, aber ich habe hoffentlich eine Erweiterungsmethode zu anderen Menschen zu helfen, die auf diese 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);
}

Interessanterweise ist die HttpWebResponse.GetResponseStream(), die Sie vom WebException.Response bekommen ist nicht das gleiche wie die Antwortstream, die Sie vom Server empfangen hätten. In unserer Umwelt sind zu verlieren, wir tatsächlich Antworten Server, wenn ein 400 HTTP-Status Code zurück an den Client unter Verwendung der HttpWebRequest/HttpWebResponse Objekte zurückgegeben. Von dem, was wir gesehen haben, ist die Antwort Strom mit dem WebException's HttpWebResponse zugeordnet ist, an dem Client generiert und mit einen des Antworttext nicht vom Server enthalten. Sehr frustrierend, da wir zurück an den Client der Grund für die schlechte Anfrage zu der Mitteilung wünschen.

ich ähnliche Probleme hatten, als die Google-OAuth2 Dienst zu verbinden versucht.

Ich landete manuell den POST schreiben, nicht WebRequest verwenden, wie folgt aus:

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, der Sie nach.

Insbesondere mein Problem war, dass ich Endlinien zwischen url-kodierten Datenstücken setzen. Wenn ich sie nahm, war alles. Sie könnten eine ähnliche Technik verwenden können, um Ihren Service zu verbinden und den tatsächlichen Antwortfehlertext lesen.

Versuchen Sie dies (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<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
    {
        try
        {
            return await request.GetResponseAsync();
        }
        catch(WebException ex)
        {
            return ex.Response;
        }
    }

Dies löste es für mich:
https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77

TL; DR:
Problem:
localhost Renditen erwartet Inhalt, Remote-IP ändert 400 Inhalt zu „Bad Request“
Lösung:
Hinzufügen <httpErrors existingResponse="PassThrough"></httpErrors> web.config/configuration/system.webServer dies für mich gelöst; jetzt alle Server (lokale und remote) Rückkehr des exakt gleichen Inhalts (von mir erzeugt), unabhängig von der IP-Adresse und / oder HTTP-Code, den ich zurück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top