ASP.NET Code
  Home arrow ASP.NET Code arrow Global error handling with e-mail notifica...
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Silverlight  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
ASP Web Hosting  
ASP.NET Web Hosting 
Windows Web Hosting
 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
ASP.NET CODE

Global error handling with e-mail notification
By: Tyler Peelen
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 1
    2002-08-21

    Table of Contents:

    Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    In this article I am going to share some techniques on globally trapping and handling errors that occur in a web application and then how to notify administrators/developers that the error has occurred. I will use the Application_OnError subroutine of the global.asax file to trap the errors and then the aspNetEmail component to send the error notification e-mails.[bold]Introduction[/bold]When porting our campus? student information portal to ASP.NET, we realized that the previous ASP ...In this article I am going to share some techniques on globally trapping and handling errors that occur in a web application and then how to notify administrators/developers that the error has occurred. I will use the Application_OnError subroutine of the global.asax file to trap the errors and then the aspNetEmail component to send the error notification e-mails.[bold]Introduction[/bold]When porting our campus? student information portal to ASP.NET, we realized that the previous ASP version generated many errors that we had no idea had occurred. It was decided that in the new version we needed some way to trap errors and then e-mail us information about the error.We didn?t want to use System.Web.Mail because our administrators did not want to install SMTP server on all of our web servers. After looking around a bit, we decided to go with the aspNetEmail component, which in addition to allowing us to use our single campus SMTP server, also allowed for us to dynamically create the HTML error e-mails and include DataGrids.[bold]Error Trapping[/bold]Error trapping and handling at an application level is super easy to do in ASP.NET. All errors occur at the application level, so you can trap errors using the Application_OnError method of global.asax.In our Application_OnError subroutine, we grab the exception for the error using Context.Error.GetBaseException() as seen in the code below:


    Sub Application_Error(ByVal sender As ObjectByVal e As EventArgs)
    Dim ex As Exception Context.Error.GetBaseException()

    Dim objErrHandler As New ErrorHandler()
    objErrHandler.SendHtmlErrorEmail(ex)
    End Sub

    After the exception is grabbed, it is passed to the SendHtmlErrorEmail function of the ErrorHandler class, which does the work of generating the e-mail.[bold]Collecting additional information[/bold]In addition to being sent information about the error itself, we also needed to be sent information about the session that generated the error, like QueryString & Form variables, Server Variables and Cookies. This kind of information helps tremendously in the bug-tracking process.We wanted to get the variables into a DataTable so that later we could easily bind it to a DataGrid. The variables are either stored in a NameValueCollection or an HttpCookiesCollection, so I wrote a couple of functions that iterate through the collections and add rows to a datatable:


     Private Function GetVariables(ByVal inputVarCollection As System.Collections.Specialized.NameValueCollection) As DataTable
    Dim objTable 
    As New DataTable()
    objTable.Columns.Add("Name"GetType(String))
    objTable.Columns.Add("Value"GetType(String))

    Dim strItem As String
    Dim objRow 
    As DataRow
    For Each strItem In inputVarCollection
    objRow 
    objTable.NewRow()
    objRow("Name") = strItem
    objRow
    ("Value") = inputVarCollection(strItem)
    objTable.Rows.Add(objRow)
    Next

    Return objTable
    End 
    Function

    Private Function 
    GetCookieVars() As DataTable
    Dim objTable 
    As New DataTable()
    objTable.Columns.Add("Name"GetType(String))
    objTable.Columns.Add("Value"GetType(String))

    Dim strItem As String
    Dim objRow 
    As DataRow
    For Each strItem In HttpContext.Current.Request.Cookies
    objRow 
    objTable.NewRow()
    objRow("Name") = strItem
    objRow
    ("Value") = HttpContext.Current.Request.Cookies(strItem).Value
    objTable
    .Rows.Add(objRow)
    Next

    Return objTable
    End 
    Function

    [bold]Creating the DataGrids[/bold]I fashioned the error e-mail after the output generated when you use ASP.NET tracing. The easiest way to do this was to use DataGrids, but since they were all going to be the same design and they needed to be programmatically generated on the fly, I wrote a method that set up the templates for the grid:


    Private Function CreateDataGrid() As System.Web.UI.WebControls.DataGrid

    Dim objDataGrid 
    As New DataGrid()
    objDataGrid.Width System.Web.UI.WebControls.Unit.Percentage(100)
    objDataGrid.BorderWidth System.Web.UI.WebControls.Unit.Pixel(0)
    objDataGrid.CellPadding "2"

    objDataGrid.HeaderStyle.BackColor System.Drawing.Color.LightGray
    objDataGrid
    .HeaderStyle.ForeColor System.Drawing.Color.Black
    objDataGrid
    .HeaderStyle.Font.Name "Arial"
    objDataGrid.HeaderStyle.Font.Size System.Web.UI.WebControls.FontUnit.Point(10)
    objDataGrid.HeaderStyle.Font.Bold True

    objDataGrid
    .ItemStyle.BackColor System.Drawing.Color.White
    objDataGrid
    .ItemStyle.ForeColor System.Drawing.Color.Black
    objDataGrid
    .ItemStyle.Font.Name "Arial"
    objDataGrid.ItemStyle.Font.Size System.Web.UI.WebControls.FontUnit.Point(10)

    objDataGrid.AlternatingItemStyle.BackColor System.Drawing.ColorTranslator.FromHtml("#eeeeee")
    objDataGrid.AlternatingItemStyle.ForeColor System.Drawing.Color.Black
    objDataGrid
    .AlternatingItemStyle.Font.Name "Arial"
    objDataGrid.AlternatingItemStyle.Font.Size System.Web.UI.WebControls.FontUnit.Point(10)

    Return 
    objDataGrid

    End 
    Function

    [bold]Creating the e-mail[/bold]This is the most complicated step of the process and one of the main reasons that we went with the aspNetEmail component. System.Web.Mail didn?t allow us to add controls (like DataGrid) to an e-mail message, so we would have had to build a lot of ugly ASP-like code to generate nice, uniform looking tables. Why reinvent the wheel when there are server controls that do the dirty work for you? We were able to add the DataGrid controls to our e-mail messages using aspNetEmail?s AppendControlToBody function. The code below will add a DataGrid containing cookie information and send the e-mail:


    Dim objMessage As New EmailMessage("your smtp server")

    Dim objCookiesDG As DataGrid CreateDataGrid()
    objCookiesDG.DataSource GetCookieVars()
    objCookiesDG.DataBind()
    objMessage.AppendControlToBody(objCookiesDG)

    objMessage.FromAddress "e-mail address"
    objMessage.To "comma separated e-mail addresses"
    objMessage.Subject "Error: Portal Error"
    objMessage.BodyFormat MailFormat.Html
    objMessage
    .Send()

    [bold]Conclusion[/bold]It is super easy to globally handle and trap errors at an application level, and with a couple of steps, you can create e-mail notification of those errors in a standard, easy to read format. You can view the entire ErrorHandlerClass below:


    Imports System.Text
    Imports aspNetEmail

    Public Class ErrorHandler

    Private Function CreateDataGrid() As System.Web.UI.WebControls.DataGrid

    Dim objDataGrid 
    As New DataGrid()
    objDataGrid.Width System.Web.UI.WebControls.Unit.Percentage(100)
    objDataGrid.BorderWidth System.Web.UI.WebControls.Unit.Pixel(0)
    objDataGrid.CellPadding "2"

    objDataGrid.HeaderStyle.BackColor System.Drawing.Color.LightGray
    objDataGrid
    .HeaderStyle.ForeColor System.Drawing.Color.Black
    objDataGrid
    .HeaderStyle.Font.Name "Arial"
    objDataGrid.HeaderStyle.Font.Size System.Web.UI.WebControls.FontUnit.Point(10)
    objDataGrid.HeaderStyle.Font.Bold True

    objDataGrid
    .ItemStyle.BackColor System.Drawing.Color.White
    objDataGrid
    .ItemStyle.ForeColor System.Drawing.Color.Black
    objDataGrid
    .ItemStyle.Font.Name "Arial"
    objDataGrid.ItemStyle.Font.Size System.Web.UI.WebControls.FontUnit.Point(10)

    objDataGrid.AlternatingItemStyle.BackColor System.Drawing.ColorTranslator.FromHtml("#eeeeee")
    objDataGrid.AlternatingItemStyle.ForeColor System.Drawing.Color.Black
    objDataGrid
    .AlternatingItemStyle.Font.Name "Arial"
    objDataGrid.AlternatingItemStyle.Font.Size System.Web.UI.WebControls.FontUnit.Point(10)

    Return 
    objDataGrid

    End 
    Function

    Private Function 
    GetVariables(ByVal inputVarCollection As System.Collections.Specialized.NameValueCollection) As DataTable
    Dim objTable 
    As New DataTable()
    objTable.Columns.Add("Name"GetType(String))
    objTable.Columns.Add("Value"GetType(String))

    Dim strItem As String
    Dim objRow 
    As DataRow
    For Each strItem In inputVarCollection
    objRow 
    objTable.NewRow()
    objRow("Name") = strItem
    objRow
    ("Value") = inputVarCollection(strItem)
    objTable.Rows.Add(objRow)
    Next

    Return objTable
    End 
    Function

    Private Function 
    GetCookieVars() As DataTable
    Dim objTable 
    As New DataTable()
    objTable.Columns.Add("Name"GetType(String))
    objTable.Columns.Add("Value"GetType(String))

    Dim strItem As String
    Dim objRow 
    As DataRow
    For Each strItem In HttpContext.Current.Request.Cookies
    objRow 
    objTable.NewRow()
    objRow("Name") = strItem
    objRow
    ("Value") = HttpContext.Current.Request.Cookies(strItem).Value
    objTable
    .Rows.Add(objRow)
    Next

    Return objTable
    End 
    Function

    Public 
    Sub SendHtmlErrorEmail(ByVal ex As Exception)
    Dim objMessage As New EmailMessage("your smtp server")

    objMessage.Body "<SPAN STYLE=""font-size:18pt; color: red;font-family: Arial;"">Portal Error - " ex.Message "</SPAN>

    "

    Dim objErrInfoDG As DataGrid CreateDataGrid()

    objMessage.Body &= "<TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0><TR><TD STYLE=""background-color: black; color: white;font-weight: bold;font-family: Arial;"">Error information</TD></TR></TABLE>"
    Dim objTable As New DataTable()
    objTable.Columns.Add("Name"GetType(String))
    objTable.Columns.Add("Value"GetType(String))

    Dim objRow As DataRow

    objRow 
    objTable.NewRow()
    objRow("Name") = "Message"
    objRow("Value") = ex.Message
    objTable
    .Rows.Add(objRow)

    objRow objTable.NewRow()
    objRow("Name") = "Source"
    objRow("Value") = ex.Source
    objTable
    .Rows.Add(objRow)

    objRow objTable.NewRow()
    objRow("Name") = "TargetSite"
    objRow("Value") = ex.TargetSite.ToString()
    objTable.Rows.Add(objRow)

    objRow objTable.NewRow()
    objRow("Name") = "StackTrace"
    objRow("Value") = ex.StackTrace
    objTable
    .Rows.Add(objRow)

    objErrInfoDG.DataSource objTable
    objErrInfoDG
    .DataBind()
    objMessage.AppendControlToBody(objErrInfoDG)


    objMessage.Body &= "

    <TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0><TR><TD COLSPAN=2 STYLE=""background-color: black; color: white;font-weight: bold;font-family: Arial;"">Querystring Collection</TD></TR></TABLE>"
    Dim objQSDG As DataGrid CreateDataGrid()
    objQSDG.DataSource GetVariables(HttpContext.Current.Request.QueryString)
    objQSDG.DataBind()
    objMessage.AppendControlToBody(objQSDG)


    objMessage.Body &= "

    <TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0><TR><TD COLSPAN=2 STYLE=""background-color: black; color: white;font-weight: bold;font-family: Arial;"">Form Collection</TD></TR></TABLE>"
    Dim objFormDG As DataGrid CreateDataGrid()
    objFormDG.DataSource GetVariables(HttpContext.Current.Request.Form)
    objFormDG.DataBind()
    objMessage.AppendControlToBody(objFormDG)


    objMessage.Body &= "

    <TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0><TR><TD COLSPAN=2 STYLE=""background-color: black; color: white;font-weight: bold;font-family: Arial;"">Cookies Collection</TD></TR></TABLE>"
    Dim objCookiesDG As DataGrid CreateDataGrid()
    objCookiesDG.DataSource GetCookieVars()
    objCookiesDG.DataBind()
    objMessage.AppendControlToBody(objCookiesDG)


    objMessage.Body &= "

    <TABLE BORDER=0 WIDTH=100% CELLPADDING=1 CELLSPACING=0><TR><TD COLSPAN=2 STYLE=""background-color: black; color: white;font-weight: bold;font-family: Arial;"">Server Variables</TD></TR></TABLE>"
    Dim objServVarDG As DataGrid CreateDataGrid()
    objServVarDG.DataSource GetVariables(HttpContext.Current.Request.ServerVariables)
    objServVarDG.DataBind()
    objMessage.AppendControlToBody(objServVarDG)

    objMessage.FromAddress "e-mail address"
    objMessage.To "comma separated e-mail addresses"
    objMessage.Subject "Error: Portal Error"
    objMessage.BodyFormat MailFormat.Html
    objMessage
    .Send()
    End Sub

    End 
    Class

    [bold]About the Author[/bold]Tyler Peelen is the lead ASP.NET developer for the University of Wisconsin ? Stevens Point, my.uwsp.edu portal project. Although he is only 18, he has a firm grasp of ASP.NET has been programming for 10 years.
    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

    More ASP.NET Code Articles
    More By Tyler Peelen

     

    IBM® developerWorks developerWorks - FREE Tools!


    Check out the new Jazz space on developerWorks

    <a href="http://zeus.developershed.com/shonuff.php?blackbird=3853&zoneid=442&source=&dest=http%3A%2F%2Fwww.ibm.com%2Fdeveloperworks%2Fspaces%2Fjazz%3FS_TACT%3D105AGY31%26S_CMP%3DDEVSHED&ismap="><img src="http://images.devshed.com/corp/img/news/jazz01.gif" alt="developerWorks Jazz space" align="left"></a>You've heard the buzz about Jazz... want to know more about it from a developer's perspective? Check out the Jazz space on developerWorks. This space is an up-to-date resource for developers, including technical information about Jazz and products built on Jazz, like Rational Team Concert Express. The Jazz space includes content from a wide variety of sources, including links, feeds, and comments from experts.
    FREE! Go There Now!


    NEW! Addressing software-as-a-service challenges using Tivoli security and WebSphere solutions

    Building a software-as-a-service solution requires addressing a few key technical challenges. In this webcast, we'll focus on the role of IBM Tivoli Directory Server and WebSphere Portlet Factory in creating a Software as a Service solution. We will demonstrate how to use Tivoli Directory Server to prevent the user population of one tenant from accessing the virtual portal and portlet components of another tenant. We will also use the dynamic profile capability of WebSphere Portlet Factory to create multiple highly customized applications from one code base.
    FREE! Go There Now!


    NEW! Harnessing the power of SQL and Java for high performance data access

    Join this webcast to see how IBM Data Studio Developer and pureQuery can take the pain out of Java data access. uApplications developed using both Java and SQL have become a common requirement. Database connectivity using Java Database Connectivity (JDBC) to create an application is a multi-step tedious process, and tooling that covers both SQL and Java has been unavailable, until now. IBM Data Studio introduces the pureQuery platform: a high-performance, Java data access platform focused on simplifying the tasks of developing, managing, and optimizing database applications and services.
    FREE! Go There Now!


    NEW! Hello World: Monitor a simple business process using WebSphere Business Monitor V6.0.2

    This tutorial shows new users of IBM WebSphere Business Monitor Version 6.0.2 how to perform the "Hello World" equivalent for monitoring business process applications. It is intended to help you get familiar with the capabilities of the product.
    FREE! Go There Now!


    NEW! Rational 'Talks to You' Teleconference Series

    This Fall, IBM Rational talks to you directly through a special teleconference series giving you access to the best minds in IBM Rational - product experts and market thought leaders who will answer your questions during these pre-scheduled telephone conference calls. Register today!
    FREE! Go There Now!


    NEW! Rational Talks to You: Scott Ambler on being agile in a global development environment

    Join this Rational Talks to You teleconference on December 6 at 1:00 pm ET to participate in an agile application development discussion and get your questions answered on using IBM Rational Method Composer in a distributed environment.Get your questions answered!
    FREE! Go There Now!


    NEW! Trial download: IBM Informix Dynamic Server Express Edition V11.0

    Informix Dynamic Server (IDS) Express Edition offers outstanding online transaction processing (OLTP) database performance, while helping to simplify and automate many of the tasks associated with deploying databases for small business applications. IDS 11 further extends the ease of management and applications integration with the Admin API and Scheduler, high availability with Continuous Log Restore for backup server recovery in case of a primary server failure, and column level encryption to protect personal and company private data.
    FREE! Go There Now!


    NEW! Try IBM Rational Asset Manager V7.0 online!

    You can now evaluate IBM Rational Asset Manager V7.0 online without installing or configuring it on your own system! Rational Asset Manager helps create, modify, govern, find, and reuse any type of development assets, including SOA and systems development assets. Rational Asset Manager helps you reduce software development costs and improve quality by facilitating the reuse of all types of software development-related assets. Visit developerWorks to learn more about this product and register to explore its capabilities online.
    FREE! Go There Now!


    NEW! Webcast: Introducing the new Information Server and Solutions community: LeverageInformation

    User communities play an important role in communication and collaboration around products, solutions and other areas of special interest to members. Successful communities are able to provide the right mix of content and services to deliver a value proposition that resonates with each audience. Join Tom Inman, VP of Marketing for Information and Platform Solutions as he introduces the new LeverageINFORMATION community. During this webcast, learn about the value provided by the community and how customers and partners derive value from the community in addressing their own technical and business challenges.
    FREE! Go There Now!


    NEW! Webcast: Quickly provide customized, integrated user interfaces with Lotus Notes 8

    IBM Lotus Notes 8 provides a wide range of developers the ability to provide customized, integrated user interfaces via composite applications and via custom sidebar and toolbar plug-ins. This webcast provides you with tips and techniques to use with out-of-the-box capabilities of Lotus Notes 8, and survey how you can share useful components within your own company and within a larger community.
    FREE! Go There Now!



    All FREE IBM® developerWorks Tools!

    ASP.NET CODE ARTICLES

    - How to Use the ListBox Control in ASP.NET 2.0
    - How to Load XML Documents in ASP.NET 2.0
    - DataGrid Code
    - ASP.NET Guestbook
    - User Controls and Client Side Scripting
    - ASP.NET Programming with Microsoft's AS...
    - ASP.NET Basics (part 3): Hard Choices
    - ASP.NET Basics (part 2): Not My Type
    - ASP.NET Basics (part 1): Nothing But .Net
    - Directory Tree Browser
    - How to get the confirmation of Yes/No from a...
    - .NET LinkButton web control
    - .NET Static VariablesBetter than Applicatio...
    - .Net to Oracle Connectivity using ODBC .NET
    - A sample code to Add two DataTables in a dat...





    © 2003-2010 by Developer Shed. All rights reserved. DS Cluster 12 Hosted by Hostway
    For more Enterprise Application Development news, visit eWeek