どうすれば404をキャッチできますか?


93

私は次のコードを持っています:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";
request.Credentials = MyCredentialCache;

try
{
    request.GetResponse();
}
catch
{
}

特定の404エラーをキャッチするにはどうすればよいですか?WebExceptionStatus.ProtocolErrorは、エラーが発生したことを検出するだけで、エラーの正確なコードを提供することはできません。

例えば:

catch (WebException ex)
{
    if (ex.Status != WebExceptionStatus.ProtocolError)
    {
        throw ex;
    }
}

十分に役に立たないだけです...プロトコル例外は401、503、403など、実際には何でもかまいません。


13
NNNOOOOOOOOOOOOO! キャッチしないSystem.Exceptionでください。ハンドラの例外テキストに依存しないでください。
アーロノート

2
ジョン・サンダースの答えが最も完全でした。人々は彼を不意に捨てたと思う。
アーロノート

3
を使用しないでくださいthrow ex。空の呼び出しスタックで新しい例外が生成されます。だけを使用してくださいthrow
krbnr 2014

1
私自身、これはいつもイライラするものだと思っていました。整形式の応答が返され、プロトコルエラーメッセージが整形式である場合、例外はスローされません。このクラスでは、ユーザーが結果を解釈してそれに応じて行動できるようにする必要があります。
Jeremy Holovacs 2017

@JeremyHolovacs例外は、新しいHTTPクライアントの404などに対してスローされなくなりました。「制御フローに例外を使用しないでください」は、構築したチームを生き延びなかったようですWebRequest
Matt Kocaj

回答:


113

HttpStatusCode Enumeration具体的には、HttpStatusCode.NotFound

何かのようなもの:

HttpWebResponse errorResponse = we.Response as HttpWebResponse;
if (errorResponse.StatusCode == HttpStatusCode.NotFound) {
  //
}

どこに
weありますWebException


自分のルックアップリストを作成せずに、オブジェクトからどうにかしてNUMBERを取得できますか?int httpresponsecode = HttpStatusCode.ToInt()などのようにしたいので、404を取得します
BerggreenDK

2
あなただけのint型httpresonsecode =行うことができるはず@BerggreenDK (INT) HttpStatusCode.NotFound
TREV

7
-1私の古代の反対票の部分的な説明:なんらかの理由で、そうwe.Responseでない場合、コードはNullReferenceExceptionをスローしHttpWebResponseます。コードが常にそのタイプであると想定したい場合は、単にキャストする必要がありますHttpWebResponse errorResponse = (HttpWebResponse)we.Response;。これInvalidCastExceptionにより、不可解なことが発生した場合は、不可解なの代わりに明示的にスローされNullReferenceExceptionます。
ジョンサンダース

私が手An object reference is required for the non-static field, method, or property 'WebException.Response'にこのコードを使用しました。
ジェイミー

122
try
{
    var request = WebRequest.Create(uri);
    using (var response = request.GetResponse())
    {
        using (var responseStream = response.GetResponseStream())
        {
            // Process the stream
        }
    }
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError &&
        ex.Response != null)
    {
        var resp = (HttpWebResponse) ex.Response;
        if (resp.StatusCode == HttpStatusCode.NotFound)
        {
            // Do something
        }
        else
        {
            // Do something else
        }
    }
    else
    {
        // Do something else
    }
}

10
lol @はIDisposableの警察であり、usingブロックで応答をラップしないように全員に-1を与えます。
リッチ

2
大変な仕事ですが、誰かがやらなければなりません。OTOH、私はこの回答を追加することはほとんどありませんでした。なぜなら、私が他の皆に私を最高評価の回答にするようにと言っていたように思われるからです。
John Saunders

3
私は実際に賛成票を投じましたが、私は1つのことに気づきました。おそらくthrowの最後に(再スロー)があるはずcatchですWebException
アーロノート

@ジョン・サンダース:リクエストの周りにも使用してみませんか?
Joel Etherton、2010年

1
@Joel:をWebRequest実装していませんIDisposable
John Saunders

23

C#6では、例外フィルターを使用できます。

try
{
    var request = WebRequest.Create(uri);
    using (var response = request.GetResponse())
    using (var responseStream = response.GetResponseStream())
    {
        // Process the stream
    }
}
catch(WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound)
{
    // handle 404 exceptions
}
catch (WebException ex)
{
    // handle other web exceptions
}

私が見落としている非常にクールな機能!他の人が一般的な例外ハンドラーを通過できるようにしながら、401のみをキャッチするメソッドを探し続けました。これが方法です!
Lionet Chen 2017

12

私はこれをテストしていませんが、動作するはずです

try
{
    // TODO: Make request.
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError) {
        HttpWebResponse resp = ex.Response as HttpWebResponse;
        if (resp != null && resp.StatusCode == HttpStatusCode.NotFound)
        {
            // TODO: Handle 404 error.
        }
        else
            throw;
    }
    else
        throw;
}

@John Saunders-OPのコードを最適化するのではなく、適応させました。
MiffTheFox 2010年

@ジョン-そして、私は彼らがcatchブロックをコピー/貼り付けすることを期待していたかもしれません、試してみたところ、OPとまったく同じコードがあったためです。このとき、OPのコードにより、この質問を完全に無効にする必要があります。
MiffTheFox

1
ここで忘れている@Johnはサンプルコードです。これは、404への別の方法であり、GetResponseの使用方法ではない場合です。-1は少し厳しいようです。質問に答えるためにミフに+1。
David Basarab、2010年

@ジョンコメントで指摘してよかったと思います。私が下向き投票を見る方法は、与えられたコードが問題を解決しない場合です。反対票を削除していただきありがとうございます。
David Basarab、2010年

@ジョン-結構です、私は今、幸せなキャッチ以外のすべてを取り除きましたか?
MiffTheFox 2010年

4

WebExceptionをキャッチした場合、404かどうかを判断するために使用できるいくつかの情報があると思います。これが、現時点で私が知る唯一の方法です。他の情報を知りたいと思います...

catch(WebException e) {
    if(e.Status == WebExceptionStatus.ProtocolError) {
        var statusCode = (HttpWebResponse)e.Response).StatusCode);
        var description = (HttpWebResponse)e.Response).StatusDescription);
    }
}

2

この抜粋をチェックしてください。GetResponseはWebRequestExceptionをスローします。これをキャッチすると、応答からステータスコードを取得できます。

try {
   // Create a web request for an invalid site. Substitute the "invalid site" strong in the Create call with a invalid name.
     HttpWebRequest myHttpWebRequest = (HttpWebRequest) WebRequest.Create("invalid site");

    // Get the associated response for the above request.
     HttpWebResponse myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse();
    myHttpWebResponse.Close();
}
catch(WebException e) {
    Console.WriteLine("This program is expected to throw WebException on successful run."+
                        "\n\nException Message :" + e.Message);
    if(e.Status == WebExceptionStatus.ProtocolError) {
        Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
        Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
    }
}
catch(Exception e) {
    Console.WriteLine(e.Message);
}

これはhttp://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspxから取得されました


2

適切な例外タイプをキャッチしますWebException

try
{
    var request = (HttpWebRequest) WebRequest.Create(String.Format("http://www.gravatar.com/avatar/{0}?d=404", hashe));

    using(var response = (HttpWebResponse)request.GetResponse())
        Response.Write("has avatar");
}
catch(WebException e) 
{
  if(e.Response.StatusCode == 404) 
    Response.Write("No avatar");
}

@John Saunders私はそこでは議論しませんが、それは問題ではありませんでした、彼は404をキャプチャするための最良の方法を尋ねました。可能。
Nick Craver

@John Saunders:修正済み、「これが最も効率的である場合」が質問に適用されると思います。
Nick Craver

ただ、キャストしなければならなかったe.ResponseようHttpWebResponseにアクセスする前にStatusCode
Lankymart 2018年

2

応答のステータスについては、MSDNを参照してください。

...
catch(WebException e) {
  Console.WriteLine("The following error occured : {0}",e.Status);  
}
...

2
@John Saunders-私はそれをMSDNに渡します(ここからサンプルをコピーしました...)。このコードの目的は、StatusCodeの使用法を示すことであり、できるだけ効率的ではありません。
ドロール

2
@ジョン・サンダース-見せたい部分だけを残しました、あなたのためだけです:-)
Dror

2

これを参照するVB.NETの人々にとって、本当に404である場合にのみ、例外をキャッチできると思います。

Try
    httpWebrequest.GetResponse()
Catch we As WebException When we.Response IsNot Nothing _
                              AndAlso TypeOf we.Response Is HttpWebResponse _
                              AndAlso (DirectCast(we.Response, HttpWebResponse).StatusCode = HttpStatusCode.NotFound)

    ' ...

End Try

1

WebRequestクラスを使用してサーバーにデータをPOSTまたはGETすると、例外のタイプはWebExceptionになります。以下は、ファイルが見つからないことを示す例外のコードです。

        //Create a web request with the specified URL
            string path = @"http://localhost/test.xml1";
            WebRequest myWebRequest = WebRequest.Create(path);

       //Senda a web request and wait for response.
                try
                {
                    WebResponse objwebResponse = myWebRequest.GetResponse();
                    Stream stream= objwebResponse.GetResponseStream();

                }
                catch (WebException ex) {
                    if (((HttpWebResponse)(ex.Response)).StatusCode == HttpStatusCode.NotFound) {
                        throw new FileNotFoundException(ex.Message);
                    }

                }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.