Professional Windows hosting from ORCS Web
    
An Unrivaled Windows Hosting Experience    
1-888-313-9421  |  webteam@orcsweb.com        
From Our Clients:
"This is the third host I have tried, and you've managed to do in less than an hour what other hosts here have kept me waiting for over 2 weeks to do."

Join our community of clients at: 1-888-313-9421

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.)
ORCS Web, Managed Complex Hosting - Support
  • Click OK
  • Click OK again.

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.
Copyright © 1996-2010 ORCS Web, Inc. All rights reserved.