Site Search:
Sign in | Join | Help
4Penny.net

ASP.NET

Notes, Tricks and Tips on ASP.NET Coding

Trapping errors in an ASP.NET web site

There are legions of articles (articli?) out there on how to trap errors in ASP.NET. My purpose here is not to be bigger, better, faster. I'm only trying to blog the code that I use, so that I can use it in the next app that I write. So... keep your expectations low <smiles>

First, add code to the Global.asax:

     Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        ' Code that runs when an unhandled error occurs
        ExceptionLogger.HandleException(Server.GetLastError().GetBaseException())
        Response.Redirect("~/errorPage.aspx")
    End Sub

 

Next, add the event handler mentioned above 

Imports System
Imports System.Web
'Imports System.Diagnostics
'Imports System.Data
'Imports System.Data.SqlClient
'Imports System.Web.Mail
'Imports System.Configuration


Public Class ExceptionLogger


    Public Shared Sub HandleException(ByVal ex As Exception)
        Try


            Static logExceptions As Boolean = Convert.ToBoolean(System.Web.Configuration.WebConfigurationManager.AppSettings("logExceptions"))
            Dim ofacErrorLog As New dynData.facErrorLog
            Dim ctx As HttpContext = HttpContext.Current
            Dim strData As String = String.Empty
            'Dim eventID As Guid = System.Guid.NewGuid()
            Dim referer As String = String.Empty
            Dim oFunctions As New functions
            Dim sQuery As String = ""
            Dim sForm As String = ""
            Dim logDateTime As String = DateTime.Now.ToString()


            If Not logExceptions Then Return ' user set web.config setting to false, abort


            'initialize
            If Not ctx.Request.ServerVariables("HTTP_REFERER") Is Nothing Then
                referer = ctx.Request.ServerVariables("HTTP_REFERER").ToString()
            End If


            If Not ctx.Request.Form Is Nothing Then
                sForm = ctx.Request.Form.ToString()
            End If


            If Not ctx.Request.QueryString Is Nothing Then
                sQuery = ctx.Request.QueryString.ToString()
            End If


            strData = "SOURCE: " & ex.Source & vbCrLf & _
                "LogDateTime: " & logDateTime & vbCrLf & _
                "MESSAGE: " & ex.Message & vbCrLf & _
                "FORM: " & sForm & vbCrLf & _
                "QUERYSTRING: " & sQuery & vbCrLf & _
                "TARGETSITE: " & ex.TargetSite.ToString & vbCrLf & _
                "STACKTRACE: " & ex.StackTrace & vbCrLf & _
                "REFERER: " & referer


            'send an email
            oFunctions.sendMail(strData)



            'log the error message
            ofacErrorLog.ConnectionString = System.Web.HttpContext.Current.Session("connect")


            ofacErrorLog.errorLog_INS(strData, 75000, System.Web.HttpContext.Current.Session("user"))


        Catch ex2 As Exception


        End Try


    End Sub ' end method HandleException
End Class

 Notice that the Global.asax redirects to a generic 'An Error Has Ocurred' page. Nothing exciting there.

This code sends an email, and then does a table insert. Both of those topics are covered elsewhere in this blog.

This is the code for the error page itself

 <%@ Page Language="VB" MasterPageFile="~/MasterPage.master" AutoEventWireup="false"
    CodeFile="errorPage.aspx.vb" Inherits="errorPage" Title="Untitled Page" %>


<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
    <div style="text-align: center;">
        <table style="text-align: left; width: 300px">
            <tr>
                <td>
                    <div class="title1">
                        System Error</div>
                    A crash has occurred.
                </td>
            </tr>
            <tr>
                <td style="text-align: center">
                    <asp:AdRotator ID="ar1" runat="server" AdvertisementFile="~/ads.xml" />
                </td>
            </tr>
            <tr>
                <td>
                    The error has been logged, and the sys admin has been emailed.
                    <br />
                    <br />
                    If the issue is urgent, please contact the system administrator immediately<br />
                </td>
            </tr>
        </table>
    </div>
</asp:Content>
 

Add this to the web.config file:

  <add key="debug" value="False"/>
  <add key="logExceptions" value="True"/>
  <add key="emailServer" value="mail.myServer.com"/>
  <add key="emailUser" value="something@somewhere.com"/>
  <add key="emailRecipient" value="mrManager@it.com"/>
  <add key="emailPassword" value="secret"/>

This is the 'ads.xml' file referenced in this page. I use it to rotate a series of photos of auto crashes.

<Advertisements>
  <Ad>
    <ImageUrl>/images/crash01.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash02.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash03.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash04.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash05.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash06.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash07.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash08.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash09.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
  <Ad>
    <ImageUrl>/images/crash10.jpg</ImageUrl>
    <AlternateText>Oops</AlternateText>
  </Ad>
</Advertisements>
 

Last, the images used in the XML file above

This is the 'error log' class referenced above, and the code to create the table

 CREATE TABLE [_ErrorLog] (
 [intRowID] [int] IDENTITY (1, 1) NOT NULL ,
 [vchrErrorText] [varchar] (1000) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
 [intErrorNum] [int] NOT NULL ,
 [dtCreated] [datetime] NOT NULL CONSTRAINT [DF__ErrorLog_dtCreated] DEFAULT (getdate()),
 [vchrUserID] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY]
GO


-- =============================================
-- 
-- =============================================
-- 1/1/1900 created
IF EXISTS (SELECT name 
    FROM   sysobjects 
    WHERE  name = N'_4P_errorLog_INS' 
    AND    type = 'P')
    DROP PROCEDURE _4P_errorLog_INS
GO


CREATE PROCEDURE _4P_errorLog_INS 
-- _4P_errorLog_INS 'error', 234, 'steve'


@vchrErrorText varchar(1000), 
@intErrorNum int,
@vchrUserID varchar(15)


AS
 
INSERT INTO _errorlog (vchrErrorText  , intErrorNum ,vchrUserID ) values (@vchrErrorText, @intErrorNum, @vchrUserID)



go


grant all on _4P_errorLog_INS to public


--select * from _errorlog order by introwid desc



 

Imports System.Data
Imports Microsoft.ApplicationBlocks.Data
Imports System.Data.SqlClient
Public Class facErrorLog
    Dim m_cs As String
    Public Property ConnectionString() As String
        Get
            Return m_cs
        End Get
        Set(ByVal value As String)
            m_cs = value
        End Set
    End Property
    Sub New(ByVal connectionString As String)
        m_cs = connectionString
    End Sub
    Sub New()
    End Sub


    Sub errorLog_INS(ByVal strErrorText As String, ByVal intErrorNum As Int64, ByVal user As String)
        Try


            SqlHelper.ExecuteNonQuery(m_cs, CommandType.StoredProcedure, "_4P_errorLog_INS", _
                New SqlParameter("@vchrErrorText", strErrorText), _
                New SqlParameter("@intErrorNum", intErrorNum), _
                New SqlParameter("@vchrUserID", user))
        Catch ex As Exception
            Throw New Exception(ex.Message, ex.InnerException)


        End Try


    End Sub


End Class

Here is the 'sendmail' function mentioned above

     Public Sub sendMail(ByVal strBody As String)


        Try
            Dim strEmailServer As String = System.Web.Configuration.WebConfigurationManager.AppSettings("emailServer")
            Dim strEmailUser As String = System.Web.Configuration.WebConfigurationManager.AppSettings("emailUser")
            Dim strEmailPassword As String = System.Web.Configuration.WebConfigurationManager.AppSettings("emailPassword")
            Dim strEmailRecipient As String = System.Web.Configuration.WebConfigurationManager.AppSettings("emailRecipient")


            Dim mail As New System.Net.Mail.MailMessage(strEmailUser, strEmailRecipient)
            mail.Subject = "NGB Error"
            mail.Body = strBody


            Dim serv As New System.Net.Mail.SmtpClient(strEmailServer)
            'serv.Credentials = New System.Net.NetworkCredential(strEmailUser, strEmailPassword)


            serv.Send(mail)


        Catch ex As Exception
            'no error handling. we're already in an error loop. If this fails, we're just out of luck
        End Try


    End Sub

As always, your comments are welcome

Comments

No Comments

About Steve Gray

Steve is a seasoned (translate: old) developer in VB and ASP.NET. He spends most of his time in Dynamics GP, writing custom mods for consulting firms. Crystal reports, eConnect, VS Tools for Dynamics... anything that comes along.