我怎样才能抓到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,也不要依赖处理程序中的异常文本!
Aaronaught

2
约翰·桑德斯(John Saunders)的回答是最完整的。我认为人们只是出于恶意拒绝了他。
Aaronaught

3
不要使用throw ex,您将使用空的调用堆栈生成一个新的异常。只需使用throw
krbnr 2014年

1
我一直觉得这很令人沮丧。如果收到格式正确的响应,则不应引发异常,并且协议错误消息肯定格式正确。该类应允许用户解释结果并采取相应的措施。
杰里米·霍洛瓦奇

在较新的HTTP客户端中,不再为诸如404之类的东西引发@JeremyHolovacs异常。“不要在控制流中使用例外”似乎并没有幸免于建立的团队WebRequest
Matt Kocaj

Answers:


113

HttpStatusCode Enumeration专门使用HttpStatusCode.NotFound

就像是:

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

哪里
weWebException


我可以以某种方式从对象中获取NUMBER而无需创建自己的查找列表?我想要类似的东西:int httpresponsecode = HttpStatusCode.ToInt()或类似的文件,所以我得到404
BerggreenDK

2
@BerggreenDK你应该能够只是做httpresonsecode = INT (INT) HttpStatusCode.NotFound
崔佛

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
大声笑@是IDisposable的警察,并给每个人-1表示不将响应包装在using块中。
Rich

2
这是一项艰巨的工作,但必须有人做。太太了,我几乎没有添加这个答案,因为似乎我在恳求其他所有人使我的评分最高。
约翰·桑德斯

3
我实际上投票赞成,但我只是注意到一件事:在throw您的结尾处可能应该有一个(重新抛出)catch,否则,它将静默地吃掉任何其他类型的WebException
Aaronaught

@约翰·桑德斯(John Saunders):为什么您的请求也没有用处?
乔尔·埃瑟顿

1
@Joel:WebRequest没有实现IDisposable
约翰·桑德斯

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的方法,同时让其他方法传递给常规异常处理程序。这是要走的路!
莱昂内·陈

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年

@John-也许我只是希望他们复制/粘贴该catch块,因为在尝试中我拥有与OP完全相同的代码。由于OP的代码,您真的应该完全否定这个问题。
MiffTheFox 2010年

1
@John,我们忘记了这里是示例代码。在这种情况下,它是404的另一种方式,而不是如何使用GetResponse。-1似乎有点苛刻。+1给米夫(Miff)回答问题。
David Basarab 2010年

@John,我认为您可以在评论中指出这一点很好。我看不起投票的方式是,如果给出的代码不能解决问题。感谢您删除不赞成票。
David Basarab 2010年

@John-很好,我摆脱了一切,现在高兴了吗?
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

看看这个snipit。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):固定,我想“如果这是最有效的”,使其适用于该问题。
尼克·克雷弗

只是不得不投 e.ResponseHttpWebResponse在获得访问权限之前, as StatusCode
Lankymart '18 -10-26

2

有关响应状态,请参见MSDN

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

2
@John Saunders-我非常乐意将其传递给MSDN(我从此处复制了示例)。此代码的目的是显示StatusCode的用法,而不是尽可能地高效。
Dror 2010年

2
@John Saunders-我只剩下我想展示的部分,只为你:-)
Dror 2010年

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

                }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.