Bir 404'ü nasıl yakalayabilirim?


95

Takip koduna sahibim:

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

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

Belirli bir 404 hatasını nasıl yakalayabilirim? WebExceptionStatus.ProtocolError yalnızca bir hata oluştuğunu algılayabilir, ancak hatanın tam kodunu vermez.

Örneğin:

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

Yeterince kullanışlı değil ... protokol istisnası 401, 503, 403 olabilir, gerçekten herhangi bir şey.


13
NNNOOOOOOOOOOOOO! Yakalamayın System.Exceptionve işleyicinizdeki istisna metnine bağlı kalmayın!
Aaronaught

2
John Saunders'ın cevabı en eksiksiz olanıydı. Sanırım insanlar ona inadına oy verdi.
Aaronaught

3
Kullanmayın throw ex, boş bir çağrı yığınıyla yeni bir istisna oluşturacaksınız. Sadece kullan throw.
krbnr

1
Ben de bunu hep sinir bozucu bulmuşumdur. İyi biçimlendirilmiş bir yanıt alırsanız ve bir protokol hata mesajı kesinlikle iyi biçimlendirilmişse bir istisna atılmamalıdır. Sınıf, kullanıcının sonuçları yorumlamasına ve buna göre hareket etmesine izin vermelidir.
Jeremy Holovacs

@JeremyHolovacs istisnaları artık yeni http istemcilerinde 404 gibi şeyler için atılmıyor. "Kontrol akışı için istisnalar kullanma" inşa takımı hayatta görünmüyorduWebRequest
Matt Kocaj

Yanıtlar:


115

Kullanım HttpStatusCode EnumerationözellikleHttpStatusCode.NotFound

Gibi bir şey:

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

Nerede
webir olduğunu WebException.


kendi arama listemi yapmadan nesnelerden bir şekilde NUMBER'ı alabilir miyim? Şunun gibi bir şeye sahip olmak istiyorum: int httpresponsecode = HttpStatusCode.ToInt () veya benzeri, böylece 404
BerggreenDK

2
@BerggreenDK sadece int httpresonsecode = (int) HttpStatusCode.NotFound
Trev

8
Benim eski downvote -1 Kısmi açıklama: nedense, eğer kod NullReferenceException atar we.Responsedeğildir HttpWebResponse. Kod her zaman bu tip olacak varsaymak isterse, o zaman basitçe döküm olmalıdır: HttpWebResponse errorResponse = (HttpWebResponse)we.Response;. Bu InvalidCastException, imkansız olursa gizemli yerine açık bir şekilde ortaya çıkarır NullReferenceException.
John Saunders

Ben olsun An object reference is required for the non-static field, method, or property 'WebException.Response'bu kodu kullanarak.
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 @ IDisposable polis olmak ve yanıtı kullanan bir bloğa sığdırmamak için herkese -1 veriyor.
Zengin

2
Bu zor bir iş ama birinin yapması gerekiyor. OTOH, bu cevabı neredeyse eklemedim, çünkü diğer herkesi benimkini en çok oy alan cevap yapmak için kandırıyormuşum gibi görünebilir.
John Saunders

3
Aslında olumlu oy verdim, ancak bir şeyi fark ettim: Muhtemelen throwsonunda bir (yeniden atma) olmalı catch, aksi takdirde bu sessizce başka herhangi bir türü yer WebException.
Aaronaught

@John Saunders: Neden isteğiniz etrafında bir kullanımınız yok?
Joel Etherton

1
@Joel: WebRequestgerçekleştirmez IDisposable.
John Saunders

25

C # 6'da istisna filtreleri kullanabilirsiniz .

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
}

Gözden kaçırdığım çok güzel bir özellik! Başkalarının genel istisna işleyicisine geçmesine izin verirken yalnızca 401'i yakalamak için yöntemler araştırmaya devam ettim. Gitmenin yolu bu!
Lionet Chen

Olağanüstü, bu kabul edilen cevap olmalı.
Lucas925

12

Bunu test etmedim ama çalışmalı

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'nin kodunu optimize etmiyor, uyarlıyordum.
MiffTheFox

@John - Ve belki catchde OP ile denemede tam olarak aynı koda sahip olduğum için bloğu kopyalayıp yapıştırmalarını bekliyordum . O zaman OP'nin kodu nedeniyle bu soruyu tamamen geri çevirmelisiniz.
MiffTheFox

1
@John burada unuttuğumuz örnek kod. Bu, GetResponse'un nasıl kullanılacağı değil, 404'e giden başka bir yoldur. -1 biraz sert görünüyor. Soruyu yanıtladığı için Miff'e +1.
David Basarab

@John Bence bunu bir yorumda belirtmen iyi oldu. Aşağı oylamaya bakma şeklim, verilen kodun sorunu çözmemesi. Olumsuz oyu kaldırdığın için teşekkürler.
David Basarab

@John - Güzel, yakalamak dışında her şeyden kurtuldum, şimdi mutlu musun?
MiffTheFox

4

Sanırım bir WebException'ı yakalarsanız , 404 olup olmadığını belirlemek için kullanabileceğiniz bazı bilgiler var. Şu anda bildiğim tek yol bu ... Başkalarını tanımak isterim ...

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

2

Bu parçacığa bir bakın. GetResponse bir WebRequestException oluşturacaktır. Bunu yakalayın ve yanıttan durum kodunu alabilirsiniz.

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

bu http://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspx adresinden geldi


2

Uygun istisna türünü yakalayın 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 sizinle orada tartışmıyorum, ama soru bu değildi, 404'ü yakalamanın en iyi yolunu sordu. Kodunda yaptığım değişiklikler, değişikliği olabildiğince basit ve açık hale getirmek için soruyu yanıtlamakla sınırlıydı. mümkün.
Nick Craver

@John Saunders: Düzeltildi, sanırım "bu en verimli ise" soruya uygulanmasını sağlıyor.
Nick Craver

Sadece dökme zorunda e.Responseolduğu HttpWebResponseerişim elde etmeden önce StatusCode.
Lankymart

2

Yanıtın durumu hakkında MSDN'de bakın :

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

2
@John Saunders - Bunu MSDN'ye iletmekten çok mutlu olacağım (örneği kopyaladığım yer ...). Bu kodun amacı, Durum Kodunun kullanımını göstermek, mümkün olduğu kadar verimli olmamaktır.
Dror

2
@John Saunders - Sadece göstermek istediğim kısmı bıraktım, Sadece senin için :-)
Dror

2

Buna göz atan VB.NET kullanıcıları için istisnayı ancak gerçekten bir 404 ise yakalayabileceğimize inanıyorum.

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 sınıfını kullanarak sunucuya POST veya GET verisi aldığında, istisna türü WebException olacaktır.

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

                }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.