我处于这样一种情况,当我从服务器获得HTTP 400代码时,服务器完全合法地告诉我我的请求出了什么问题(使用HTTP响应内容中的消息)
然而,当状态码为400时,. net HttpWebRequest会引发一个异常。
我该怎么处理呢?对我来说,400是完全合法的,而且相当有用。HTTP内容有一些重要的信息,但是异常使我偏离了我的路径。
我处于这样一种情况,当我从服务器获得HTTP 400代码时,服务器完全合法地告诉我我的请求出了什么问题(使用HTTP响应内容中的消息)
然而,当状态码为400时,. net HttpWebRequest会引发一个异常。
我该怎么处理呢?对我来说,400是完全合法的,而且相当有用。HTTP内容有一些重要的信息,但是异常使我偏离了我的路径。
如果有某种方法可以关闭“throw on non-success code”,那就太好了,但如果你捕捉到webeexception,你至少可以使用响应:
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以确保获得整个错误。
Interestingly, the HttpWebResponse.GetResponseStream() that you get from the WebException.Response is not the same as the response stream that you would have received from server. In our environment, we're losing actual server responses when a 400 HTTP status code is returned back to the client using the HttpWebRequest/HttpWebResponse objects. From what we've seen, the response stream associated with the WebException's HttpWebResponse is generated at the client and does not include any of the response body from the server. Very frustrating, as we want to message back to the client the reason for the bad request.
我在尝试连接谷歌的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编码的数据块之间放置了端点。当我把它们拿出来的时候,一切都正常了。您可以使用类似的技术连接到您的服务并读取实际的响应错误文本。
我知道这个问题很久以前就有答案了,但我做了一个扩展方法,希望能帮助其他遇到这个问题的人。
代码:
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);
}
试试这个(这是vb代码:):
Try
Catch exp As WebException
Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try
扩展函数的异步版本:
public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
{
try
{
return await request.GetResponseAsync();
}
catch(WebException ex)
{
return ex.Response;
}
}
这为我解决了问题: https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77
TL;博士: 问题: localhost返回预期的内容,远程IP更改400内容为“坏请求” 解决方案: 添加<httpErrors existingResponse="PassThrough"></httpErrors>到web.config/configuration/system。webServer为我解决了这个问题;现在所有服务器(本地和远程)返回完全相同的内容(由我生成),而不管我返回的IP地址和/或HTTP代码。