>
Ever client always asks for error handling. They always want to display a “friendly” error page to their customers/viewers, other than the ASP.NET yellow “Application Error in ‘/’”…you know what I’m talking about!
Well, as I’m sure you are aware, this is easy in ASP.NET:
In the web.config we can add a customErrors section:
<customErrors mode="On" defaultRedirect="Error.htm" >
<error statusCode="403" redirect="Error_403.htm" />
<error statusCode="404" redirect="Error_404.htm" />
</customErrors>
Now when an error occurs it redirects to you default error page or a specific error page based on Status Code. Great right?
Well… no not really! Why??
404 Good, 302 Bad
When ASP.NET handles these errors it does two things:
- Creates a HTTP status of “Found 302” which means the data requested actually resides under a different URL (the redirect URL).
- Redirects you to the error page with a HTTP status of “OK 200”
You can see this in Firebug (or Fiddler) for the two pages:
“So why is this bad? My users still see a friendly page!”
Basically search engines prefer “hard 404s” and will improve SEO. Check out this blog post from Google: http://googlewebmastercentral.blogspot.com/2008/08/farewell-to-soft-404s.html
Give me the solution already!
We still want to make sure that we can use the web.config to control our error messages/pages and don’t want to be messing with IIS, so the solution is to capture the error in the global.ascx Application_Errror:
protected void Application_Error(object sender, EventArgs e)
{
var config = WebConfigurationManager.OpenWebConfiguration("~/Web.config");
var customErrors = config.GetSection("system.web/customErrors") as CustomErrorsSection;
if (customErrors != null && customErrors.Mode == CustomErrorsMode.On)
{
var app = (HttpApplication) sender;
Exception lastError = app.Server.GetLastError();
var httpEx = lastError as HttpException;
if (httpEx != null)
{
int httpErrorCode = httpEx.GetHttpCode();
string redirect = customErrors.DefaultRedirect;
foreach (CustomError error in customErrors.Errors)
{
if (error.StatusCode == httpErrorCode) redirect = error.Redirect;
}
app.Server.ClearError();
app.Context.Response.StatusCode = httpErrorCode;
Server.Transfer(redirect, false);
}
}
}
This solution displays your custom error page AND returns the correct HTTP status code (404 Not Found in this case) AND not redirect to the error page URL due to the Server.Transfer method to appose a Redirect.
Now everybody is happy: Your client gets there error handling page, users get a friendly message and the search engines get their Status Code!


>Very nice, almost exactly what I needed for a webapp in 2.0 .
I didn't get around to test it, but it seems that from 3.5 on you can use the CustomErrorsRedirectMode attribute to specify ResponseRewrite.
>I personally prefer handling errors the way you described as a workaround. Mostly because when handling them in Application_Error I can log them wherever I want to. If my customer sees an error page I want to know of it as well to be able to track it down later.
However it seems like a big bug that the Web.Config was doesn't work correctly.
>This worked just fine. Able to pretty much just copy paste. Got thrown for awhile by ooVoo intercepting the 404 return code and throwing up its own search results page. Beware, other web add-ons might also do that.