98
votes

I have the following code:

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

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

How can I catch a specific 404 error? The WebExceptionStatus.ProtocolError can only detect that an error occurred, but not give the exact code of the error.

For example:

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

Is just not useful enough... the protocol exception could be 401, 503, 403, anything really.

10
NNNOOOOOOOOOOOOO! Don't catch System.Exception, and don't depend on the exception text in your handler!Aaronaught
John Saunders' answer was the most complete. I think people just downvoted him out of spite.Aaronaught
Don't use throw ex, you'll generate a new exception with an empty call stack. Just use throw.krbnr
I've always found this to be frustrating, myself. An exception shouldn't be thrown if you get a well-formed response, and a protocol error message is definitely well-formed. The class should allow the user to interpret the results and act accordingly.Jeremy Holovacs
@JeremyHolovacs exceptions are no longer thrown for things like 404 in newer http clients. "Don't use exceptions for control flow" didn't seem to survive the team who built WebRequestMatt Kocaj

10 Answers

125
votes
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
    }
}
119
votes

Use the HttpStatusCode Enumeration, specifically HttpStatusCode.NotFound

Something like:

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

Where
we is a WebException.

29
votes

In C# 6 you can use exception filters.

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
}
12
votes

I haven't tested this, but it should work

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;
}
4
votes

I think if you catch a WebException there is some information in there that you can use to determine if it was a 404. That's the only way I know of at the moment...I'd be interested in knowing any others...

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

Check out this snipit. The GetResponse will throw a WebRequestException. Catch that and you can get the status code from the response.

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

this came from http://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspx

2
votes

Catch the proper exception type 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");
}
2
votes

See at MSDN about status of the response:

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

For VB.NET folks browsing this, I believe we can catch the exception only if it truly is a 404. Something like:

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
2
votes

when POST or GET data to the server using WebRequest class then the type of exception would be WebException.Below is the code for file not found exception

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