views:

1614

answers:

8

I'm trying to determine the best way to implement a 404 page in a standard ASP.NET web application. I currently catch 404 errors in the Application_Error event in the Global.asax file and redirect to a friendly 404.aspx page. The problem is that the request sees a 302 redirect followed by a 404 page missing. Is there a way to bypass the redirect and respond with an immediate 404 containing the friendly error message?

Does a web crawler such as Googlebot care if the request for a non existing page returns a 302 followed by a 404?

+1  A: 

You can configure IIS itself to return specific pages in response to any type of http error (404 included).

Assaf Lavie
+12  A: 

You can use the web.config to send 404 errors to a custom page.

    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
        <error statusCode="403" redirect="NoAccess.htm" />
        <error statusCode="404" redirect="FileNotFound.htm" />
    </customErrors>
Robin Day
I tried this and it still seems to be responding with a 302 to FileNotFound.htm. Maybe the FileNotFound.htm is returned with a 404, but the initial response is still a 302 redirect. Are you seeing the same thing?
Ben Mills
This by itself results in a 302 (at least with IIS 7). Should:1. Do customErrors as above for 404.2. In Application_Error (global.asax or error module) check for 404, and if so: Server.ClearError(); Server.Transfer("/page-not-found.aspx");3. In 404 page: Response.Status = "404 Not Found"; Response.StatusCode = 404;
Ted
+3  A: 

Easiest answer: don't do it in code, but configure IIS instead.

Pontus Gagge
A: 

Do you use this anywhere?

 Response.Status="404 Page Not Found"
DrG
A: 

I think the best way is to use the custom errors construct in your web.config like below, this let's you wire up pages to handle all of the different HTTP codes in a simple effective manner.

James
+1  A: 

I can see that setting up the 404 page in the web.config is a nice clean method, BUT it still initially responds with a 302 redirect to the error page. As an example, if you navigate to:

http://stackoverflow.com/x.aspx

you'll be redirected via a 302 redirect to:

http://stackoverflow.com/404?aspxerrorpath=/x.aspx

What I want to happen is this:

http://www.cnn.com/x.aspx

There's no redirect. A request for the missing URL returns a 404 status code with a friendly error message.

Ben Mills
+5  A: 

Handle this in your Global.asax's OnError event:

protected void Application_Error(object sender, EventArgs e){
  // An error has occured on a .Net page.
  var serverError = Server.GetLastError() as HttpException;

  if (null != serverError){
    int errorCode = serverError.GetHttpCode();

    if (404 == errorCode){
      Server.ClearError();
      Server.Transfer("/Errors/404.aspx");
    }
  }
}

In you error page, you should ensure that you're setting the status code correctly:

Response.StatusCode = 404;
Response.Message = "Page not found";

You can also handle the various other error codes in here quite nicely.

Google will generally follow the 302, and then honour the 404 status code - so you need to make sure that you return that on your error page.

Zhaph - Ben Duguid
Perfect. I forgot about the Server.Transfer() method. I'm already using the Application_Error event, so now I'll just call Server.Transfer() rather than Response.Redirect().
Ben Mills
No probs, glad to help :)
Zhaph - Ben Duguid
At least with IIS 7 there's not even a 302 temporary redirect with the above. The gotcha for me was discovering that Server.ClearError() is imperative for 404s (or else still did the redirect, not transfer).
Ted
Should that 404.htm page be an .aspx page so that you can add Response.StatusCode = 404 in the code-behind?
codeulike
@codeulike: Good catch, this was a copy from an MCMS instance, which uses an ISAPI filter to map the url to things in it's database, and so ignores the extension. The page in question did indeed have an .aspx page behind it.
Zhaph - Ben Duguid
Ah, I get it. Thanks.
codeulike
A: 

You can also check this article for more details

paxer