Custom Errors in IIS 5 or 6 using Classic ASP or ASP.NET
Steve Schofield
August 15, 2005
Introduction
This article covers how to setup and use the Custom Errors options offered in IIS
(Internet Information Server) as well as using ASP.NET to track 404 and 500 errors
specifically. For all types of users, receiving a "404: webpage not found" or a
"500: internal server error" is often frustrating. From the end-user experience,
this could potentially have the visitor not come back to your website. This article
introduces a technique that captures these errors and sends them to a database.
Classic ASP and ASP.NET have different ways to control the user experience when
an error occurs. Classic ASP relies on IIS "Custom Errors" section to redirect when
an error happens. ASP.NET uses settings in the section contained within the site's
web.config file. This can make it difficult if your website has a combination of
HTML, ASP and ASP.NET pages. Using multiple unique configurations can be impossible
sometimes if you are in a shared hosting environment.
The solution outlined in this article with record all errors in a single database,
regardless of page extension. This article covers how to setup, record and report
on these errors. Hopefully this will help make the end user experience more enjoyable
and keep them coming back day after day.
Webpage to process, record the error in a database
The first step is to develop a dynamic webpage (ASP or ASP.NET) that will capture
and record to a database. In the interest of keeping a narrow overall scope, this
article will not go into details associated with the actual construction of the
error page. For our purposes, we simply need to capture and record to the database.
This article will use the error pages from ASPFree.com. At the time, it was easier
to have separate pages for the 404 and 500 errors, however this could easily be done in a single webpage. To get started, create two files named 404.aspx and 500.aspx
at the root of your website, copying and pasting the code
below into them
404 webpage - 404.aspx
<%@ Page Language="VB" Trace="True" %>
<%@ Import Namespace="System.data" %>
<%@ Import Namespace="System.data.sqlclient" %>
<%@ Import Namespace="system.configuration" %>
<script language="VB" runat=server>
Sub Page_Load(Sender as Object, E as EventArgs)
If (Not Request.QueryString("aspxerrorpath") Is Nothing) Then
Dim objConn As SqlConnection = New SqlConnection(ConfigurationSettings.AppSettings("dbConn"))
Dim pg as string = Request.QueryString("aspxerrorpath").ToString()
Dim cmd as SQLCommand = new SqlCommand("sp_tblNotFoundPages", objConn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New SqlParameter("@strPageLookedfor", SqlDbType.VarChar, 500))
cmd.Parameters("@strPageLookedfor").Value = pg
cmd.Parameters.Add(New SqlParameter("@strTypeOfError", SqlDbType.VarChar, 50))
cmd.Parameters("@strTypeOfError").Value = "404"
objConn.Open()
cmd.ExecuteNonQuery()
objConn.Close()
End If
End Sub
</script>
<html>
<head>
</head>
<body>
This page has not been found, we have record this error and notified webmaster.
</body>
</html>
500 webpage - 500.aspx
<%@ Page Language="VB" Trace="True" %>
<%@ Import Namespace="System.data" %>
<%@ Import Namespace="System.data.sqlclient" %>
<%@ Import Namespace="system.configuration" %>
<script language="VB" runat=server>
Sub Page_Load(Sender as Object, E as EventArgs)
If (Not Request.QueryString("aspxerrorpath") Is Nothing) Then
Dim objConn As SqlConnection = New SqlConnection(ConfigurationSettings.AppSettings("dbConn"))
Dim pg as string = Request.QueryString("aspxerrorpath").ToString()
Dim cmd as SQLCommand = new SqlCommand("sp_tblNotFoundPages", objConn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(New SqlParameter("@strPageLookedfor", SqlDbType.VarChar, 500))
cmd.Parameters("@strPageLookedfor").Value = pg
cmd.Parameters.Add(New SqlParameter("@strTypeOfError", SqlDbType.VarChar, 50))
cmd.Parameters("@strTypeOfError").Value = "500"
objConn.Open()
cmd.ExecuteNonQuery()
objConn.Close()
End If
End Sub
</script>
<html>
<head>
</head>
<body>
This page had an error or it's not found. Please retry again if you feel this was
in error.
</body>
</html>
How to setup Custom Errors on your web server
- Log into the server as a user with Administrative privileges
- In IIS 6, do the following - Click Start, Program Files, Administrative Tools, and
Internet Information Services (IIS) Manager
- In IIS 5, do the following - Click Start, Program Files, Administrative Tools, and
Internet Server Manager
- Right Click on the website you want to modify, and chose properties
Note: This procedure needs to be replicated for the 500 error setting as only the
404 settings are outlined below.
- Select the error you want to modify (404 is shown above)
- Click Edit
- Select Message Type: URL
- In the URL field, type in /404.aspx (this can be any webpage in the root of your
website. 404.aspx is the page we are using to record errors to a database.)
How to configure ASP.NET to capture 404 and 500 errors
Note: If you are using Classic ASP, feel free to move on to the
"Setting up the Database" section.
The next step is to configure the site's web.config file. Unlike HTML and ASP pages
that rely on the Custom Errors settings within IIS, ASP.NET uses the <customErrors/>
section in the site's web.config file for directions on how to handle a given error.
There are three potentials values, all of which are case sensitive: "On", "Off"
and "RemoteOnly". For this article we will need the value to be set to "On".
Note: For additional information regarding the web.config file
and it's settings, please refer to this article on MSDN.
web.config used in this example
<configuration>
<appSettings>
<addkey="dbConn"value="server=your_DBServer;uid=
your_UID;pwd=your_PWD;Database=your_DB" />
</appSettings>
<system.web>
<customErrors defaultRedirect="/404.aspx" mode="On">
<error statusCode="404" redirect="/404error.aspx" />
<error statusCode="500" redirect="/500error.aspx" />
</customErrors>
</system.web>
</configuration>
Setting up the database
The last step is to setup the Database with the table and stored procedure that
will store the information. You will need to contact your hosting provider or have
access to SQL Enterprise manager or SQL Query Analyzer to process the .SQL file,
adding the necessary table and stored procedure.
Note:
When first implemented on ASPFree.com, the process just recorded the raw detail
data to the database. This meant if a page returned an error 10 times in a day,
there were 10 records in the database.
With over 15,000 unique documents on this
site, this made for many thousands of records. The original goal was to capture
the raw data and do a roll-up process later on. This added a lot of complexity and
made the database grow to nearly 500 MB. Also, trying to roll-up a lot of records
into a summary report was time-consuming and database intensive. Over time, a much
simpler and more effective process was developed. In the end, changes where made
to the stored procedure logic so that they would record a single database record
for each page on a per day basis. Then a column to record raw number of hits for
each page was added. The one drawback was that it was impossible to report when
and what website was causing the error. For example, if a search engine such as
Google or Yahoo had a bad link indexed, it was necessary to search the IIS log files
to see who was sending the bad link. There was no perfect solution without adding
more logic, however to meet the needs in that particular situation this technique
provided more than enough information to help keep 404 and 500 errors to a minimum.
Table
CREATE TABLE [dbo].[tblNotFoundPages] (
[Id] [int] IDENTITY (1, 1) NOT NULL ,
[pagelookedfor] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[DateofError] [datetime] NULL ,
[numOfHits] [int] NULL ,
[TypeOfError] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblNotFoundPages] ADD
CONSTRAINT [DF_tblNotFoundPages_numOfHits] DEFAULT (1) FOR [numOfHits],
CONSTRAINT [PK_tblNotFoundPages3] PRIMARY KEY CLUSTERED
(
[Id]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
Stored Procedure
CREATE PROCEDURE dbo.sp_tblNotFoundPages
(
@strPageLookedfor varchar(500),
@strTypeOfError varchar(50)
)
AS
Declare @chkRecord int
Declare @numOfHits int
Declare @DateOfError datetime
set @DateOfError = convert(char(10), getDate(), 101)
If exists (select Id from tblNotFoundPages where pagelookedfor = @strPagelookedfor
and @strPagelookedfor and DateOfError=@DateOfError) + 1
UPDATE tblNotFoundPages
SET numOfHits = @numOfHits
WHERE pagelookedfor = @strPagelookedfor and DateOfError=@DateOfError
End
ELSE
INSERT INTO tblNotFoundPages(pagelookedfor, TypeOfError, DateOfError) VALUES (@strPagelookedfor,
@strTypeOfError, @DateOfError)
GO
Conclusion
Hopefully you will find this solution helpful in tracking down errors on your website,
such as broken links, missing images or coding errors. Once everything is setup
correctly, attempting to access a page that is not located on your website, such
as http://yoursite.com/PageNotFound99.asp, will record the error in the database.
Steve Schofield is a Senior Internet support specialist at ORCS Web, Inc. - a company that provides managed hosting solutions for clients who develop and deploy their applications on Microsoft Windows platforms. Services include shared hosting, dedicated hosting, and webfarm hosting, with specialty in .Net, SQL Server, and architecting highly scalable solutions.