我处于这样一种情况,当我从服务器获取HTTP 400代码时,这是服务器告诉我请求出了什么问题的完全合法方法(使用HTTP响应内容中的消息)
但是,.NET HttpWebRequest在状态代码为400时引发异常。
我该如何处理?对我来说400是完全合法的,并且非常有帮助。HTTP内容包含一些重要信息,但是异常使我无法正常工作。
我处于这样一种情况,当我从服务器获取HTTP 400代码时,这是服务器告诉我请求出了什么问题的完全合法方法(使用HTTP响应内容中的消息)
但是,.NET HttpWebRequest在状态代码为400时引发异常。
我该如何处理?对我来说400是完全合法的,并且非常有帮助。HTTP内容包含一些重要信息,但是异常使我无法正常工作。
Answers:
如果有某种方法可以关闭“抛出不成功的代码”,那就太好了,但是如果您捕获了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);
}
WebException.Response
可以并且可能是null
。如果是这种情况,您应该重新抛出。
HttpClient
它,它的可配置性要强得多,我相信这是未来的方式。
((WebRequest) null).GetResponseWithoutException()
实际上不会造成NullReferenceException
,因为它被编译为的等价物,因此WebRequestExtensions.GetResponseWithoutException(null)
不会导致NullReferenceException
,因此需要输入验证。
有趣的是HttpWebResponse.GetResponseStream()
,您从那里获得WebException.Response
的与您从服务器那里收到的响应流不同。在我们的环境中,当使用对象将400 HTTP状态代码返回给客户端时,我们将丢失实际的服务器响应HttpWebRequest/HttpWebResponse
。从我们看到的情况来看,与关联的响应流WebException's HttpWebResponse
是在客户端生成的,不包含来自服务器的任何响应主体。非常令人沮丧,因为我们想向客户发送错误请求的原因。
尝试连接到Google的OAuth2服务时遇到了类似的问题。
我最终不使用WebRequest手动编写POST,如下所示:
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编码的数据段之间放置了结尾。当我将它们取出时,一切正常。您也许可以使用类似的技术连接到服务并读取实际的响应错误文本。
这为我解决了:
https //gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77
TL; DR:
问题:
localhost的回报预期的内容,远程IP涂改400的内容为“错误的请求”
解决方案:
添加<httpErrors existingResponse="PassThrough"></httpErrors>
到web.config/configuration/system.webServer
解决这对我来说; 现在,无论我返回的IP地址和/或HTTP代码如何,所有服务器(本地和远程)都返回完全相同的内容(由我生成)。