221

私は、サーバーから HTTP 400 コードを取得したときに、サーバーが要求の何が問題だったかを (HTTP 応答コンテンツのメッセージを使用して) 伝える完全に合法的な方法であるという状況にあります。

ただし、ステータス コードが 400 の場合、.NET HttpWebRequest は例外を発生させます。

どうすればこれを処理できますか? 私にとって 400 は完全に合法であり、かなり役に立ちます。HTTP コンテンツにはいくつかの重要な情報が含まれていますが、例外によって道に迷ってしまいます。

4

7 に答える 7

382

「成功しないコードをスローする」をオフにする方法があればいいのですが、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、エラー全体を取得できるように微調整する必要があります。

于 2009-03-28T07:07:08.280 に答える
50

これはずっと前にすでに回答されていることは知っていますが、この質問に来る他の人を助けるために拡張メソッドを作成しました。

コード:

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);
}
于 2013-01-17T17:56:48.930 に答える
14

興味深いことに、HttpWebResponse.GetResponseStream()から取得したWebException.Responseは、サーバーから受信したはずの応答ストリームと同じではありません。私たちの環境では、オブジェクトを使用して400 HTTP ステータスコードがクライアントに返されると、実際のサーバー レスポンスが失われHttpWebRequest/HttpWebResponseます。これまで見てきたことから、に関連付けられた応答ストリームWebException's HttpWebResponseはクライアントで生成され、サーバーからの応答本文は含まれません。悪いリクエストの理由をクライアントにメッセージで返したいので、非常にイライラします。

于 2010-04-20T15:29:56.047 に答える
13

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 エンコードされたデータの間にエンドラインを入れていたことです。私がそれらを取り出したとき、すべてがうまくいきました。同様の手法を使用してサービスに接続し、実際の応答エラー テキストを読み取ることができる場合があります。

于 2011-07-19T23:02:48.150 に答える
6

これを試してください(VBコードです:-):

Try

Catch exp As WebException
  Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try
于 2014-03-25T15:02:54.267 に答える
3

拡張関数の非同期バージョン:

    public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
    {
        try
        {
            return await request.GetResponseAsync();
        }
        catch(WebException ex)
        {
            return ex.Response;
        }
    }
于 2015-02-10T16:25:33.987 に答える