. Net HttpWebRequest.GetResponse() wyświetla wyjątek, gdy zwracany jest kod statusu http 400 (złe żądanie)

Znajduję się w sytuacji, w której gdy otrzymuję kod HTTP 400 z serwera, jest to całkowicie legalny sposób serwera mówiący mi, co było nie tak z moim żądaniem (używając wiadomości w treści odpowiedzi HTTP)

Jednak HttpWebRequest. NET podnosi wyjątek, gdy kod stanu wynosi 400.

Jak sobie z tym poradzić? Dla mnie 400 jest całkowicie legalne i raczej pomocne. Zawartość HTTP zawiera kilka ważnych informacji, ale wyjątek odrzuca mnie ze ścieżki.

Author: chefsmart, 2009-03-28

6 answers

Byłoby miło, gdyby był jakiś sposób na wyłączenie "throw on non-success code", ale jeśli złapiesz WebException, możesz przynajmniej użyć odpowiedzi:

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

Możesz zamknąć bit" get me a response even if it 's not a success code" w osobnej metodzie. (Proponuję jeszcze wrzucić, jeśli nie ma odpowiedzi, np. jeśli nie można połączyć.)

Jeśli odpowiedź błędu może być duża (co jest nietypowe), możesz zmienić HttpWebRequest.DefaultMaximumErrorResponseLength aby upewnić się, że otrzymasz cały błąd.

 316
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 11:49:56

Wiem, że odpowiedź na to pytanie została udzielona już dawno temu, ale stworzyłem metodę rozszerzenia, aby pomóc innym osobom, które zadają to pytanie.

Kod:

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

Użycie:

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);
}
 42
Author: Matthew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 13:03:54

Miałem podobne problemy podczas próby połączenia się z usługą Google OAuth2.

Skończyłem pisząc POST ręcznie, nie używając WebRequest, tak:

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

Odpowiedź, która zostanie zapisana do strumienia odpowiedzi, zawiera konkretny tekst błędu, którego szukasz.

W szczególności moim problemem było to, że umieszczałem linie końcowe między kodowanymi URL fragmentami danych. Kiedy je wyjąłem, wszystko działało. Być może będziesz w stanie użyć podobnej techniki, aby połączyć się z Twoim usługa i odczytać rzeczywisty tekst błędu odpowiedzi.

 11
Author: Jugglist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-19 23:02:48

Co ciekawe, HttpWebResponse.GetResponseStream(), które otrzymujesz z WebException.Response, nie jest tym samym, co strumień odpowiedzi, który otrzymałbyś z serwera. W naszym środowisku tracimy rzeczywiste odpowiedzi serwera, gdy kod 400 HTTP status zostanie zwrócony klientowi za pomocą obiektów HttpWebRequest/HttpWebResponse. Z tego, co widzieliśmy, strumień odpowiedzi skojarzony z WebException's HttpWebResponse jest generowany u klienta i nie zawiera żadnego ciała odpowiedzi z serwera. Bardzo frustrujące, ponieważ chcemy przekazać do klienta przyczyny złego żądania.

 11
Author: Christopher Bartling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-23 23:36:28

Try this (it ' s VB-Code : -):

Try

Catch exp As WebException
  Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try
 5
Author: Bernd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 14:04:25

Asynchroniczna wersja funkcji rozszerzenia:

    public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
    {
        try
        {
            return await request.GetResponseAsync();
        }
        catch(WebException ex)
        {
            return ex.Response;
        }
    }
 3
Author: HuStmpHrrr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 05:56:18