Bagaimana saya bisa menangkap 404?


95

Saya memiliki kode berikut:

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

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

Bagaimana saya bisa menangkap kesalahan 404 tertentu? WebExceptionStatus.ProtocolError hanya dapat mendeteksi bahwa kesalahan terjadi, tetapi tidak memberikan kode kesalahan yang tepat.

Sebagai contoh:

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

Tidak cukup berguna ... pengecualian protokol bisa jadi 401, 503, 403, apa saja.


13
NNNOOOOOOOOOOOOO! Jangan menangkap System.Exception, dan jangan bergantung pada teks pengecualian di handler Anda!
Aaronaught

2
Jawaban John Saunders adalah yang paling lengkap. Saya pikir orang-orang hanya merendahkan dia karena dendam.
Aaronaught

3
Jangan gunakan throw ex, Anda akan membuat pengecualian baru dengan tumpukan panggilan kosong. Gunakan saja throw.
krbnr

1
Saya selalu merasa ini membuat saya frustrasi. Pengecualian tidak boleh diberikan jika Anda mendapatkan respons yang dibentuk dengan baik, dan pesan kesalahan protokol sudah pasti terbentuk dengan baik. Kelas harus mengizinkan pengguna untuk menafsirkan hasil dan bertindak sesuai.
Jeremy Holovacs

Pengecualian @JeremyHolovacs tidak lagi diterapkan untuk hal-hal seperti 404 di klien http yang lebih baru. "Jangan gunakan pengecualian untuk aliran kontrol" tampaknya tidak bertahan tim yang dibangunWebRequest
Matt Kocaj

Jawaban:


115

Gunakan HttpStatusCode Enumeration, secara khususHttpStatusCode.NotFound

Sesuatu seperti:

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

Dimana
wea WebException.


dapatkah saya mengeluarkan NOMOR dari objek tanpa membuat daftar pencarian saya sendiri? Saya ingin memiliki sesuatu seperti: int httpresponsecode = HttpStatusCode.ToInt () atau yang serupa jadi saya mendapatkan 404
BerggreenDK

2
@BerggreenDK Anda harus dapat melakukan int httpresonsecode = (int) HttpStatusCode.NotFound
Trev

8
-1 Penjelasan parsial dari downvote kuno saya: kode melempar NullReferenceException jika, karena alasan tertentu, we.Responsetidak HttpWebResponse. Jika kode ingin menganggap bahwa ia akan selalu memiliki jenis itu, maka harus hanya melemparkan: HttpWebResponse errorResponse = (HttpWebResponse)we.Response;. Ini akan melemparkan eksplisit InvalidCastExceptionjika hal yang tidak mungkin terjadi, bukannya misterius NullReferenceException.
John Saunders

Saya An object reference is required for the non-static field, method, or property 'WebException.Response'menggunakan kode ini.
Jamie

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 @ menjadi polisi IDisposable dan memberi semua orang -1 karena tidak membungkus respons dalam blok penggunaan.
Kaya

2
Ini pekerjaan yang sulit, tetapi seseorang harus melakukannya. OTOH, saya hampir tidak menambahkan jawaban ini, karena sepertinya saya memaksa orang lain untuk menjadikan jawaban saya sebagai jawaban teratas.
John Saunders

3
Saya benar-benar menaikkan suara, tetapi saya hanya memperhatikan satu hal: Mungkin harus ada throw(putar ulang) di akhir Anda catch, jika tidak, ini hanya akan memakan jenis lainnya secara diam-diam WebException.
Aaronaught

@ John Saunders: Mengapa Anda tidak menggunakan permintaan Anda juga?
Joel Etherton

1
@ Joel: WebRequesttidak diimplementasikan IDisposable.
John Saunders

25

Di C # 6 Anda dapat menggunakan filter pengecualian .

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
}

Fitur yang sangat keren yang pernah saya abaikan! Saya terus mencari metode untuk menangkap hanya 401 sementara membiarkan orang lain lolos ke pengendali pengecualian umum. Inilah cara untuk pergi!
Lionet Chen

Luar biasa, ini harus menjadi jawaban yang diterima.
Lucas925

12

Saya belum menguji ini, tetapi seharusnya berhasil

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 - Saya mengadaptasi kode OP, tidak mengoptimalkannya.
MiffTheFox

@ John - Dan mungkin saya hanya mengharapkan mereka untuk menyalin / menempelkan catchblok, mengingat saya memiliki kode yang sama persis dalam percobaan sebagai OP. Anda harus benar-benar mengabaikan pertanyaan ini sama sekali karena kode OP itu.
MiffTheFox

1
@ John kami lupa di sini adalah contoh kode. Kasus ini adalah cara lain untuk 404, bukan cara menggunakan GetResponse. -1 tampak sedikit kasar. +1 ke Miff untuk menjawab pertanyaan itu.
David Basarab

@ John Saya pikir itu baik Anda menunjukkannya dalam komentar. Cara saya melihat ke bawah voting adalah jika kode yang diberikan tidak menyelesaikan masalah. Terima kasih telah menghapus suara tidak setuju.
David Basarab

@ John - Baik, aku sudah menyingkirkan semuanya kecuali tangkapannya, senang sekarang?
MiffTheFox

4

Saya rasa jika Anda menemukan WebException ada beberapa informasi di sana yang dapat Anda gunakan untuk menentukan apakah itu adalah 404. Itulah satu-satunya cara yang saya ketahui saat ini ... Saya tertarik untuk mengetahui yang lain ...

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

2

Lihat snipit ini. GetResponse akan menampilkan WebRequestException. Tangkap itu dan Anda bisa mendapatkan kode status dari respons.

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);
}

ini berasal dari http://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspx


2

Tangkap jenis pengecualian yang tepat 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 Saya tidak memperdebatkan Anda di sana, tapi bukan itu pertanyaannya, dia menanyakan cara terbaik untuk mendapatkan 404. Perubahan saya pada kodenya hanya terbatas untuk menjawab pertanyaan, untuk membuat perubahan sesederhana dan sejelas bisa jadi.
Nick Craver

@ John Saunders: Diperbaiki, saya kira "jika ini yang paling efisien" membuatnya berlaku untuk pertanyaan.
Nick Craver

Hanya harus melemparkan e.Responseas HttpWebResponsesebelum mendapatkan akses ke StatusCode.
Lankymart

2

Lihat di MSDN tentang status tanggapan:

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

2
@ John Saunders - Saya akan dengan senang hati meneruskannya ke MSDN (tempat saya menyalin sampel dari ...). Tujuan kode ini adalah untuk menunjukkan penggunaan StatusCode, tidak seefisien mungkin.
Dror

2
@John Saunders - Saya hanya menyisakan bagian yang ingin saya tunjukkan, Hanya untuk Anda :-)
Dror

2

Untuk orang-orang VB.NET yang menjelajah ini, saya yakin kami dapat menangkap pengecualian hanya jika itu benar-benar adalah 404. Sesuatu seperti:

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

ketika POST atau GET data ke server menggunakan kelas WebRequest maka jenis pengecualiannya adalah WebException. Di bawah ini adalah kode untuk pengecualian file tidak ditemukan

        //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);
                    }

                }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.