首页 文章

.Net HttpWebRequest.GetResponse()在返回http状态代码400(错误请求)时引发异常

提问于
浏览
191

我遇到的情况是,当我从服务器获取HTTP 400代码时,服务器告诉我我的请求有什么问题(使用HTTP响应内容中的消息)是完全合法的方式

但是,当状态代码为400时,.NET HttpWebRequest会引发异常 .

我该如何处理?对我来说,400是完全合法的,而且非常有帮助 . HTTP内容有一些重要的信息,但异常使我离开了我的道路 .

6 回答

  • 5

    如果有某种方法可以关闭“抛出非成功代码”,那将会很好,但是如果你捕获WebException,你至少可以使用响应:

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

    你可能想在一个单独的方法中封装“让我得到一个响应,即使它不是成功代码” . (如果没有回复,我建议你仍然扔,例如,如果你无法连接 . )

    如果错误响应可能很大(这是不寻常的),您可能需要调整HttpWebRequest.DefaultMaximumErrorResponseLength以确保您收到整个错误 .

  • 326

    我知道很久以前就已经回答了这个问题,但我做了一个扩展方法,希望能帮助其他人来解决这个问题 .

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

    Usage:

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

    尝试连接到Google的OAuth2服务时,我遇到了类似的问题 .

    我最终手动编写POST,而不是使用WebRequest,如下所示:

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

    写入响应流的响应包含您所追踪的特定错误文本 .

    特别是,我的问题是我在URL编码的数据片段之间放置了 endpoints . 当我拿出它们时,一切正常 . 您可以使用类似的技术连接到您的服务并阅读实际的响应错误文本 .

  • 42

    有趣的是,从 WebException.Response 获得的 HttpWebResponse.GetResponseStream() 与您从服务器收到的响应流不同 . 在我们的环境中,当使用 HttpWebRequest/HttpWebResponse 对象将 400 HTTP status 代码返回给客户端时,我们将丢失实际的服务器响应 . 根据我们所看到的,与 WebException's HttpWebResponse 关联的响应流在客户端生成,不包括服务器的任何响应主体 . 非常令人沮丧,因为我们想要向客户端发回错误请求的原因 .

  • 11

    试试这个(这是VB代码:-):

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

    扩展函数的异步版本:

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

相关问题