HttpWebRequest.GetResponse()が失敗したときにエラー情報を取得する方法


86

HttpWebRequestを開始してから、その応答を取得しています。ときどき、500(または少なくとも5 ##)のエラーが発生しますが、説明がありません。私は両方のエンドポイントを制御しており、受信側にもう少し情報を取得してもらいたいです。たとえば、サーバーからクライアントに例外メッセージを渡したいと思います。これはHttpWebRequestとHttpWebResponseを使用して可能ですか?

コード:

try
{
    HttpWebRequest webRequest = HttpWebRequest.Create(URL) as HttpWebRequest;
    webRequest.Method = WebRequestMethods.Http.Get;
    webRequest.Credentials = new NetworkCredential(Username, Password);
    webRequest.ContentType = "application/x-www-form-urlencoded";
    using(HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)
    {
        if(response.StatusCode == HttpStatusCode.OK)
        {
            // Do stuff with response.GetResponseStream();
        }
    }
}
catch(Exception ex)
{
    ShowError(ex);
    // if the server returns a 500 error than the webRequest.GetResponse() method
    // throws an exception and all I get is "The remote server returned an error: (500)."
}

これに関する助けをいただければ幸いです。

回答:


151

これはHttpWebRequestとHttpWebResponseを使用して可能ですか?

Webサーバーで例外テキストをキャッチして応答の本文に書き込み、ステータスコードを500に設定することができます。これで、クライアントは500エラーが発生したときに例外をスローしますが、応答ストリームを読み取ってフェッチすることができます。例外のメッセージ。

したがって、200以外のステータスコードがサーバーから返された場合にスローされるWebExceptionをキャッチして、その本体を読み取ることができます。

catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    using (var reader = new StreamReader(stream))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}
catch (Exception ex)
{
    // Something more serious happened
    // like for example you don't have network access
    // we cannot talk about a server exception here as
    // the server probably was never reached
}

ありがとうございました!usingステートメントの内側からのストリームは、webResponseのディスポーザーがクリアするため、usingステートメントの外側では使用できないことに注意してください。これは私を数分間つまずかせた。
トーリン2012

@Thorin。最初のステートメントからの「ストリーム」は、次のステートメントに引き継がれます。1行のIFステートメントと同じように、たとえばif(something)do-stuff-here;
RealityDysfunction 2014

1
GetRequestStreamそしてGetResponse投げることができる例外を
PreguntonCojoneroCabrón

@PreguntonCojoneroCabrónうん、それは完全に正しくないようだ、そうだ。ありがたいことに、MicrosoftはHttpClientクラスを導入しました。これは、最近ほとんどの人が使用していると思います。msdn.microsoft.com/en-us/library/...
モルテンNørgaard

8

FTPサイトにファイルが存在するかどうかを確認しようとしたときに、この質問に出くわしました。ファイルが存在しない場合、タイムスタンプを確認しようとするとエラーが発生します。しかし、タイプをチェックして、エラーが他のものではないことを確認したいと思います。

Responseプロパティは、そのプロパティをチェックして、発生しているFTPエラーを確認できるWebExceptionタイプFtpWebResponseになります。StatusCode

これが私が最終的に得たコードです:

    public static bool FileExists(string host, string username, string password, string filename)
    {
        // create FTP request
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + host + "/" + filename);
        request.Credentials = new NetworkCredential(username, password);

        // we want to get date stamp - to see if the file exists
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        try
        {
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            var lastModified = response.LastModified;

            // if we get the last modified date then the file exists
            return true;
        }
        catch (WebException ex)
        {
            var ftpResponse = (FtpWebResponse)ex.Response;

            // if the status code is 'file unavailable' then the file doesn't exist
            // may be different depending upon FTP server software
            if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                return false;
            }

            // some other error - like maybe internet is down
            throw;
        }
    }

4

私は同様の状況に直面しました:

BasicHTTPBindingを使用して、SOAPサービスを消費するHTTPエラーの場合に生の応答を読み取ろうとしていました。

ただし、を使用して応答を読み取るとGetResponseStream()、エラーが発生しました。

ストリームが読めない

だから、このコードは私のために働いた:

try
{
    response = basicHTTPBindingClient.CallOperation(request);
}
catch (ProtocolException exception)
{
    var webException = exception.InnerException as WebException;
    var rawResponse = string.Empty;

    var alreadyClosedStream = webException.Response.GetResponseStream() as MemoryStream;
    using (var brandNewStream = new MemoryStream(alreadyClosedStream.ToArray()))
    using (var reader = new StreamReader(brandNewStream))
        rawResponse = reader.ReadToEnd();
}

0

HttpWebRequestとResponseを、結果に基づいてオブジェクトを返す単純なメソッドにラップするこのライブラリを使用することもできます。これらの回答で説明されている手法のいくつかを使用しており、このスレッドや同様のスレッドからの回答に触発されたコードがたくさんあります。例外を自動的にキャッチし、これらのWeb要求を行うために必要なボイラープレートコードを可能な限り抽象化しようとし、応答オブジェクトを自動的に逆シリアル化します。

このラッパーを使用してコードがどのように見えるかの例は、次のように単純です。

    var response = httpClient.Get<SomeResponseObject>(request);
    
    if(response.StatusCode == HttpStatusCode.OK)
    {
        //do something with the response
        console.Writeline(response.Body.Id); //where the body param matches the object you pass in as an anonymous type.  
    }else {
         //do something with the error
         console.Writelint(string.Format("{0}: {1}", response.StatusCode.ToString(), response.ErrorMessage);

    }

完全な開示 このライブラリは無料のオープンソースラッパーライブラリであり、私はそのライブラリの作者です。私はこれでお金を稼ぐことはできませんが、何年にもわたって非常に役立つことがわかりました。まだHttpWebRequest / HttpWebResponseクラスを使用している人もきっとそうするでしょう。

これは特効薬ではありませんが、getとpost、およびJSONまたはXMLの要求と応答に対して、非同期と非非同期の両方でget、post、deleteをサポートします。2020年6月21日現在、積極的に整備されています。


-3
HttpWebRequest myHttprequest = null;
HttpWebResponse myHttpresponse = null;
myHttpRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpRequest.Method = "POST";
myHttpRequest.ContentType = "application/x-www-form-urlencoded";
myHttpRequest.ContentLength = urinfo.Length;
StreamWriter writer = new StreamWriter(myHttprequest.GetRequestStream());
writer.Write(urinfo);
writer.Close();
myHttpresponse = (HttpWebResponse)myHttpRequest.GetResponse();
if (myHttpresponse.StatusCode == HttpStatusCode.OK)
 {
   //Perform necessary action based on response
 }
myHttpresponse.Close(); 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.