我遇到的情况是,当我从服务器获取HTTP 400代码时,服务器告诉我我的请求有什么问题(使用HTTP响应内容中的消息)是完全合法的方式
但是,当状态代码为400时,.NET HttpWebRequest会引发异常.
我该如何处理?对我来说,400是完全合法的,而且非常有帮助.HTTP内容有一些重要的信息,但异常使我离开了我的道路.
如果有某种方法可以关闭"抛出非成功代码",那将会很好,但是如果你捕获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
以确保获得整个错误.
我知道很久以前就已经回答了这个问题,但我做了一个扩展方法,希望能帮助其他人来解决这个问题.
码:
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); }
有趣的是HttpWebResponse.GetResponseStream()
,您从中获得WebException.Response
的与您从服务器收到的响应流不同.在我们的环境中,当使用对象将400 HTTP状态代码返回给客户端时,我们将丢失实际的服务器响应HttpWebRequest/HttpWebResponse
.从我们所看到的,与该关联的响应流WebException's HttpWebResponse
在客户端生成,并且不包括来自服务器的任何响应主体.非常令人沮丧,因为我们想要向客户端发回错误请求的原因.
尝试连接到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编码的数据片段之间放置了端点.当我拿出它们时,一切正常.您可以使用类似的技术连接到您的服务并阅读实际的响应错误文本.
试试这个(这是VB代码:-):
Try Catch exp As WebException Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd End Try