.Net HTTP状态代码400(错误的请求)返回时,HttpWebRequest.GetResponse()引发exception

我处于这种情况,当我从服务器获取HTTP 400代码时,服务器完全合法地告诉我我的请求出了什么问题(在HTTP响应内容中使用消息)

但是,状态码为400时,.NET HttpWebRequest引发exception。

我该如何处理? 对我来说,400是完全合法的,而且相当有帮助。 HTTP内容有一些重要的信息,但是这个例外将我抛弃了我的道路。

如果有某种方式closures“抛出非成功的代码”会很好,但是如果你发现WebException,你至less可以使用这个响应:

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

您可能想要在单独的方法中封装“即使不是成功代码也能得到响应”位。 (如果没有回应,我build议你还是扔掉,例如,如果你不能连接。)

如果错误的响应可能很大(这是不寻常的),你可能想要调整HttpWebRequest.DefaultMaximumErrorResponseLength ,以确保你得到了整个错误。

我知道这个已经被很久以前的答案了,但是我做了一个延伸的方法,希望能够帮助到这个问题的其他人。

码:

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

用法:

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

有趣的是,从WebException.Response获得的HttpWebResponse.GetResponseStream()与您从服务器接收到的响应stream不一样。 在我们的环境中,当使用HttpWebRequest / HttpWebResponse对象将400 HTTP状态代码返回给客户端时,我们正在丢失实际的服务器响应。 从我们所看到的,与WebException的HttpWebResponse关联的响应stream在客户端生成,并且不包含来自服务器的任何响应主体。 非常令人沮丧,因为我们想要向客户反馈错误请求的原因。

尝试连接到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); } 

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

特别是,我的问题是我在URL编码的数据块之间放了个端点。 当我拿出来的时候,一切都奏效了。 您可能可以使用类似的技术连接到您的服务,并阅读实际的响应错误文本。

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

 Catch exp As WebException 'Read the real response from the server Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd 

一个asynchronous版本的扩展函数:

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

我跑了一个类似的问题,后来..debugging我的代码后,我发现我做的交易逻辑上是错误的..小计是0.25美元和贝宝服务器看到它,拒绝处理,并给我400个不好的要求