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

StackOverflow https://stackoverflow.com/questions/692342

  •  22-08-2019
  •  | 
  •  

我遇到的情况是,当我从服务器获取 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相关的响应流,不包括任何来自服务器的响应主体的。非常令人沮丧,因为我们希望信息返回给客户端的坏请求的原因。

试图连接到谷歌的服务的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);
}

这被写入到响应流响应包含了你之后的特定错误文本。

在特别是,我的问题是,我是把网址编码的数据片之间endlines。当我就拿出来,一切正常。您可能能够使用类似的技术来连接到您的服务,并读取实际响应错误文本。

尝试此(它的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; DR:结果 的问题:结果 本地主机的回报预期的内容,远程IP改变了400的内容为“错误的请求”结果 的解决方案:结果 添加<httpErrors existingResponse="PassThrough"></httpErrors>web.config/configuration/system.webServer解决了这个对我来说;现在所有的服务器(本地和远程),而不管返回的IP地址和/或HTTP代码我返回的完全相同的内容(通过我生成)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top