Customize '404' Errors
Learn how to make customized error pages and provide better direction for your users.
By Josef Finsel
How can I replace the standard error page that shows up when someone enters a link that doesn't exist with something that can help them?
- M.A., Fort Thomas, Ky.
This is an extremely relevant question, especially considering the change from ASP Classic to ASP.NET. Consider: Anyone who links to your site needs to change their links from names such as "default.asp" to "default.aspx" for instance. With a little work, though, you can keep people from seeing the dreaded "404" error and point them to the correct page.
Let's start at the beginning: how IIS handles 404 errors. If you go into your IIS manager and right-click on a Web site, you get the properties dialog box, containing - among others - the Custom Errors tab (see Figure 1). As you can see, there is a whole directory of pages found in C:\WINNT\Help\iisHelp\common. You can open any of these files in a browser and see the familiar error pages and variations. You can find a whole list of the HTTP Status Codes at http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html, but we are interested only in the 400series (client error) and the 500 series (server error), because these are the only ones MS allows us to create custom pages for.
Figure 1. The Custom Errors tab in the Properties dialog in IIS lets you see what errors you can create custom pages for and where the default pages are located.
Let's take a look at the 404 error. The HTML file for that error is 404b.html. If you open it in the browser you'll find the generic "File Not Found" page that signifies broken links. Your first task, then, is to create a page to replace this one. That's where your .NET Redirecting Error page enters the picture.
Before building the page, take a look at how IIS implements custom errors. If you're using a static file - such as 404b.html - IIS leaves the original link in the address bar and returns the static HTML file. When you replace the static file with a URL, though, any QueryString data is stripped and the address that created the URL is passed as a QueryString to the error page (see QueryString, Params, and Forms - Oh My!). The resulting address looks like this:
The question mark (?) defines the beginning of the data, the 404 represents the Status code, and the semicolon (;) separates the code from the URL that generated it. If there were a sub code related to the status code, it would be after the status code and before the URL. So, 401-1;http://localserver/CustomError_CS/WebForm1.asp indicates a failed login to the page. 401-3;http://localserver/CustomError_CS/WebForm1.asp indicates an Authorized Control List failure. In any case, the first thing we need to do is separate out the requested Web page that caused the 404 error. This requires some basic string manipulation to take RawUrl and parse it to get all the information after the question mark (?) and semicolon (;):
string s404Page = Request.RawUrl;
s404Page = s404Page.Substring(s404Page.IndexOf("?")+1);
s404Page = s404Page.Substring(s404Page.IndexOf(";")+1);
With this information, you then can try to determine what page the user was attempting to go to. If the site has been upgraded to .NET, the user might have been following a link pointed to the .asp version of the page. In this case, you easily can redirect them to the .aspx version by adding an "x" to the s404Page variable and issuing a Server.Redirect to the .aspx page:
// We need to redirect to an .aspx page
string s404Redirect = s404Page + "x";
Assuming a valid .aspx page exists, the user is redirected to the .aspx page. This is a good start, but it introduces a secondary problem if the ASP.NET page doesn't exist. That's because the ASP.NET filter handles 404 errors differently than the ASP Classic filter does. To handle 404 errors for ASP.NET errors, you need to modify the web.config file's customErrors section like this:
This turns on customErrors, so the error section creates an entry to handle 404 errors, redirecting the browser to your CustomError.ASPX page. The QueryString generated by the ASP.NET 404 error looks like this:
Unlike redirecting an .asp page to an .aspx page, you can't simply remedy this by appending an "x" to the extension. You need to come up with something else. Some people send the browser to the home page when a 404 error is encountered. Then, however, the user would never know there had been a problem. If your Web site is searchable, you might want to implement a search page here with a message that the page the user seeks doesn't exist, but they can search for the information they wanted. As another alternative, you could direct them to your sitemap. This article's downloadable code sample simply informs the user that the page is incorrect and then offers a link to the home page (see end of article for download details).
Let me comment on one last item you might want to consider. If you frequently use QueryString variables in your Web pages, you might want to leave your .asp files in place, but use them strictly to redirect the user to the .NET version of the page. For instance, I have a number of database-driven pages that use QueryString variables to display data. If I remove these pages and let the custom 404 page handle links, I'll end up sending folks to blank pages. Instead, I simply use the .asp pages to redirect the browser to the .aspx version of the page with the QueryString intact, which is transparent to the user.
The files referenced in this article are available for download in both VB .NET and C#.
Have a question? Send it to [email protected].
Josef Finsel is a software consultant with G.A. Sullivan, a global software development company. He has published a number of VB and SQL Server-related articles and is working on the syntax for FizzBin.NET, a programming language that works the way programmers have always suspected. He's also author of The Handbook for Reluctant Database Administrators (Apress).