You are here: Home > Articles > Article Display

A custom '404 Page Not Found' in ASP.NET

We will create a custom 404 Response error page in ASP.NET, which will produce a friendly output to the user and send an email to the webmaster letting them know about the broken link so they can fix it.

Published: Jun 10, 2002
Tested with: ASP.NET 1.1
Category: ASP.NET
48,259 views

Introduction

In this article we will see how to create a custom 404 Response error page in ASP.NET, which will:

  1. produce a friendly output to the user
  2. send an email to the webmaster letting them know about the broken link so they can fix it.

The default 404 page

When we link to a URL that does not exist, the web server sends back a 404 Response. This basically tells us that the requested resource does not exist. Microsoft's Internet Information Server (IIS) is set up to send a default HTML page when it encounters this kind of error. This page, along with others making up the default server errors, are created upon installation of IIS. You have probably seen it many times while browsing:

default 404 Page Not Found page

This output is simply an HTML file which usually resides (depending on your installation) in C:\WINNT\help\iisHelp\common\404b.htm.

Why should we change the default page?

A quick look at the screen capture above should convince you right away that this is not the most user-friendly page. In fact, a user who sees this will probably abandon your site. There is no way for them to know what happened. Did the page move? What site is this? What are my options now?

Since this is a standard HTML page, we can create our own and tell IIS to send that instead. That way, we can have a friendlier page for the user, one that has our logo for example, the same look and feel as the rest of the site, and some options of what to do now that the resource was not found. But most important of all, we can add our custom ASP code in it to perform some cool stuff, like capturing the broken link or the refering page, and then store that in a database or send an email to the webmaster. You might even want to perform a search in the background based on the URL, and present the user with some more options.

The main goal is to not let the user go away. Getting a user to come to your site is hard enough. Presenting them with a friendlier experience, even when some resource is not found, is certainly a step in the right direction in motivating them to click around.

Changing the default page in IIS

Go to Start > Programs > Administrative Tools > Internet Services Manager. Find the website you want to change in the list of sites, right click on it and select Properties. Go the the Custom Errors tab.

Custom Errors tab in IIS

Here is where you can change all the server errors that are displayed. Scroll down to the 404 HTTP Error, select it by clicking on it, and then click on Edit Properties....

Error Mapping Properties screenshot

The path to the file on your machine can vary depending on how IIS was installed. You can change the file in 2 ways:

  1. as a File, by browsing the file system and selecting the file.
  2. as a URL, by typing the virtual URL of the file.

What's the difference? You can run ASP code only if you choose a virtual file, since that is simply redirecting to a file on your site. If you have ASP.NET installed you can run .aspx files. So in our case, we will change this to a virtual file. Our custom ASPX file, which we will see below, resides at /servererrors/404.aspx. You can name it whatever you want and place it anywhere you want on your site. Therefore:

edited Error Mapping Properties dialog

Change the Message Type to URL, and type in the URL the virtual URL of the file on your site to redirect to. Click OK all the way through to save your changes.

Editing the web.config file

When someone now links to a broken link on our site, they will see this instead:

what the custom 404 page looks like

However, while this will work for almost all files extensions (.htm/.html/.asp etc.), it will not work for ASPX files. The reason is that those files pass through a special parser which instead outputs a .NET error. To get the .NET application to redirect to this custom 404 file, we need to edit our web.config file in the root of the site. Open up (if you do not have one already then create it) the web.config file in the root of your site and type this in it:

1 <configuration>
2     <system.web>
3         <customErrors mode="On">
4             <error statusCode="404" redirect="/servererrors/404.aspx" />
5         </customErrors>
6     </system.web>
7 </configuration>

Here we are telling the .NET application to turn on custom errors, and for each Response Code (like 404) we can create a separate node and redirect to a specific virtual page.

The code in 404.aspx

1 <%@ Page Language="VB" runat="server" explicit="true" strict="true" %>
2 <%@ Register TagPrefix="UserControl" TagName="Header" Src="head.ascx" %>
3 <%@ Register TagPrefix="UserControl" TagName="Footer" Src="tail.ascx" %>
4 <%@ Import Namespace="System.Web.Mail" %>
5 ...

Notice that I am registering 2 UserControls to include my header and footer. You can do something similar if you want, or take them out. They are not necessary for the code to run. I import the System.Web.Mail namespace so we can send an email to our webmaster.

1 ...
2 <script language="vb" runat="server">
3 Sub Page_Load()
4     '-- Get Query from the URL
5     Dim strQuery As String = Request.ServerVariables("QUERY_STRING")
6     '-- avoid running our code if someone browses
7     ' the 404.aspx file directly
8     If strQuery <> "" Then
9         '-- Page with the broken link
10         Dim strReferer As String = Request.ServerVariables("HTTP_REFERER")
11         '-- remove the default appended string to the url
12         strQuery = strQuery.Replace("404;http://", "")
13         '-- Find the position of the root "/" in the string
14         Dim intSlashPosition As Integer = strQuery.IndexOf("/")
15         '-- Remove all text before the "/"
16         strQuery = strQuery.Remove(0, intSlashPosition)
17         '-- set the label control's text
18         lblQueryString.Text = strQuery
19 ...

When the page loads, we can get the broken link from the URL. When a redirect to the 404 page happens, the server appends the broken link to the 404 page:

Address bar of browser showing the server appending the broken link to the URL

In the case above, the broken link was /articles/list.aspx. We can get that through the Request.ServerVariables("QUERY_STRING"). If the query is empty, then it probably means that the user found this ASPX page on our site and simply browsed to it (although highly unlikely). Nevertheless, in that case we do not want to run our code. That's why all the code is nested inside the condition that the strQuery is not empty.

1 ...
2         '-- Send Email to the Webmaster
3         Dim objMail As New MailMessage()
4         Dim strEmailBody As String
5         strEmailBody = "Xefteri - 404 Page Not Found : " & DateTime.Now & "<br>" & "------------------------------------------------------" & "<br>" & "<br>"
6         If strReferer = "" Then
7             strEmailBody = strEmailBody & "Someone typed in this broken link directly:" & "<br>"
8         Else
9             strEmailBody = strEmailBody & "The page <a href=""" & strReferer & """>" & strReferer & "</a> contains a broken link:" & "<br>"
10         End If
11         strEmailBody = strEmailBody & "<br>" & strQuery
12         '-- change the FROM and TO emails for your site
13         objMail.From = "username@someserver.com"
14         objMail.To = "username@someserver.com"
15         objMail.Subject = "Xefteri - 404 Page Not Found"
16         objMail.Priority = MailPriority.High
17         objMail.BodyFormat = MailFormat.Html
18         objMail.Body = strEmailBody
19         SmtpMail.SmtpServer = ""
20         SmtpMail.Send(objMail)
21         '-- strQuery = ""
22     Else
23         '-- switch panel displays to display the error
24         ' when a user simply navigates to this file
25         pnlValid404.Visible = False
26         pnlNotValid404.Visible = True
27     End If
28 End Sub
29 </script>
30 ...

Next, we send an email to the webmaster of the site, letting them know about the broken link and where it came from so they can take a look at it. In my HTML code I use the .NET Panel Controls to switch content. This is similar to the classic ASP where you would nest your output within Subs and depending on some condition you would display one and not the other. Panels make this easier. You can see how in the HTML code below.

1 ...
2 <html>
3 <head>
4     <meta name="robots" content="noindex,nofollow">
5     <title>Xefteri - 404 Page Not Found</title>
6     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
7 </head>
8 <body bgcolor="#FFFFFF">
9     <UserControl:Header runat="server" />
10     <h2>Page Not Found (404 Error)</h2>
11     <asp:panel id="pnlValid404" runat="server">
12         <p><asp:label id="lblQueryString" runat="server" ForeColor="#FF0000" /> could not be located.<p>
13         <p>An email has been sent to the webmaster about this problem, and action will be taken to fix it.</p>
14     </asp:panel>
15     <asp:panel id="pnlNotValid404" runat="server" Visible="False">
16         <p>This page works only as a redirect when an ASPX page is not found.</p>
17     </asp:panel>
18     <UserControl:Footer id="myFooter" runat="server" />
19 </body>
20 </html>

The UserControl Header and Footer are my include files for simply the header and footer that go on every page. The label control with ID lblQueryString outputs the strQuery from our code. And finally, the two panels switch content depending on what we want to show to the user. The pnlNotValid404 is set to not visible be default since this is our error display, and we only set it to visible if one occurs.

Conclusion

Some hosting companies will not repoint the default 404 Response page to your custom code. Some will do it for a fee. However, if your site is made up of only ASPX files, then by simply copying the web.config file in the root folder of your site will actually make this work. There is no need to edit the IIS manually. Keep in mind though, that this will only work for .aspx extensions, unless you also change the IIS.

 



Other articles in this category
  1. Smart headers and footers using ASP.NET User Controls
    December 23, 2002
    Good site usability often means removing links from one page back to itself. In this article we will look at how to create an ASP.NET User Control which will act as a common header to a site. It will automatically know which page we are looking at, and it will remove links to the same page from itself. For example, on this site, if we click on the About us section of the header, it will take you to the page, and it will make that link inactive. That way, we know that we are under that section, and we can't click on it anymore.
  2. Maintaining Sorting while Paging in an ASP.NET Datagrid
    December 18, 2002
    The Datagrid server control offers much control and flexibility in presenting data. Two of the actions that are hard-wired into it are Paging and Sorting. On their own they work great, but not so well together. When you sort a column and then move to a previous or next page, the sorting preference is not maintained. In this article we will see how to maintain both by using the Viewstate object.
  3. How postback works in ASP.NET
    December 10, 2002
    In this article, we will take a closer look at how ASP.NET pages post back to themselves, and how to customize this feature in our web applications.
  4. Viewing and editing file and directory attributes in ASP.NET
    December 2, 2002
    The System.IO.FileAttributes class gives us access to file/directory attributes. In this article, we'll see how to use this class to first read the current attributes and then change them.
  5. Copying a directory in ASP.NET
    November 25, 2002
    The System.IO.DirectoryInfo class does not come with a method to copy a directory. In this article, we'll see how to create a method to do that, and then use it in an ASP.NET page.