Home
    Shop
    Advertise
    Write For Us
    Affiliate
    Newsletter
    Contact

Application Level Error Handling in ASP.NET

ASP.NET provides many different ways for error handling. Error handling starts on page level with try-catch blocks and Page_Error procedure. To find out more about this see Errors and Exceptions in ASP.NET tutorial. This tutorial goes one step further and explains error handling on Application level. This includes handling errors with Application_Error procedure in Global.asax or by using custom http module. These methods are usually used to log error details in text file, database or Windows EventLog, or to send notification e-mails to administrator.

 

Handling errors in Application_Error in Global.asax

Global.asax is optional file. Your site can work without it, but it could be very useful. You can have only one Global.asax in the root folder of your web site. Global.asax contains Application_Error procedure which executes whenever some unhandled error occurs. By using Application_Error, you can catch all unhandled errors produced by your web site, and then write a code to save error messages to database, text file or Windows EventLog, send notificationn e-mail, write some message to user, redirect user to other page with Response.Redirect etc. If you used Server.ClearError() in Page_Error procedure, Application_Error in Global.asax will not execute. Implementation code is similar to Page_Error code above:

[ C# ]

void Application_Error(object sender, EventArgs e)
{
  // Get current exception
  Exception CurrentException = Server.GetLastError();
  string ErrorDetails = CurrentException.ToString();433333
 
  // Now do something useful, like write error log
  // or redirect a user to other page
  ...
}

[ VB.NET ]

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
  ' Get current exception
  Dim CurrentException As Exception = Server.GetLastError()
  Dim ErrorDetails As String = CurrentException.ToString()
 
  ' Now do something useful, like write error log
  ' or redirect a user to other page
  ...
 
End Sub

 

Writing errors to EventLog

One of the ways to track errors is to write them to EventLog. If your web site is on shared hosting you probably can't write to EventLog because of security issues. If you are on dedicated server, you need to enable "Full control" to EventLog for ASPNET account. You can do this in Registry Editor. Go to Start menu -> Run... and type regedt32 or regedit and press Enter. Registry Editor will show. Go to HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\, right mouse click and select Permissions... from context menu, like in image bellow.

Registry editor
Registry editor

Click on Permissions... item to show a dialog. Give Full Control to your ASP.NET Machine Account, like in next image (include child objects too!).

Registry permissions dialog
Registry permissions dialog

Now ASPNET account has enough rights. To write in EventLog we can use Try...Catch syntax or Page_Error event, but to avoid duplication of code better option is to use Application_Error in Global.asax file. Code inside Application_Event procedure will be executed every time when some error occurs on web site.

[ C# ]

void Application_Error(object sender, EventArgs e)
{
  // Get current exception
  Exception CurrentException = Server.GetLastError();
 
  // Name of the log
  string SiteLogName = "My Web Site Errors";
   
  // Check if this log name already exists
  if (EventLog.SourceExists(SiteLogName) == false)
  {
    EventLog.CreateEventSource(SiteLogName, SiteLogName);
  }
 
  // Write new error log
  EventLog NewLog = new EventLog();
  NewLog.Source = SiteLogName;
  NewLog.WriteEntry(CurrentException.ToString(), EventLogEntryType.Error);
}

[ VB.NET ]

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
  ' Get current exception
  Dim CurrentException As Exception = Server.GetLastError()
 
  ' Name of the log
  Dim SiteLogName As String = "My Web Site Errors"
  
  ' Check if this log name already exists
  If EventLog.SourceExists(SiteLogName) = False Then
    EventLog.CreateEventSource(SiteLogName, SiteLogName)
  End If
 
  ' Write new error log
  Dim NewLog As EventLog = New EventLog()
  NewLog.Source = SiteLogName
  NewLog.WriteEntry(CurrentException.ToString(), _  
    EventLogEntryType.Error)
End Sub
 

Reading web site error messages from EventLog

After we created procedure for writing site error messages to Windows EventLog, we need to read them too. You can read these messages by using Windows Event Viewer, located in Control Panel. Also, you can show these messages on web page in some kind of report. To read EventLog error messages with ASP.NET and show them on page you can use code like this:

[ C# ]

using System;
 
// We need these namespace to read EventLog
using System.Diagnostics;
 
public partial class _Default : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    // Load errors to EventLog object
    EventLog MySiteErrorLogs = new EventLog("My Web Site Errors");
 
    foreach(EventLogEntry SiteErrorLog in MySiteErrorLogs.Entries)
    {
      // Find when error occured
      Response.Write("Time generated: " +
        SiteErrorLog.TimeGenerated.ToString() + "<br />");
      // Show error details
      Response.Write(SiteErrorLog.Message + "<hr />");
    }
  }
}

[ VB.NET ]

Imports System
 
' We need these namespace to read EventLog
Imports System.Diagnostics
 
Partial Class DefaultVB
  Inherits System.Web.UI.Page
 
 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   ' Load errors to EventLog object
   Dim MySiteErrorLogs As EventLog = New EventLog("My Web Site Errors")
 
   For Each SiteErrorLog In MySiteErrorLogs.Entries
    ' Find when error occured
    Response.Write("Time generated: " & _
       SiteErrorLog.TimeGenerated.ToString() & "<br />")
    ' Show error details
    Response.Write(SiteErrorLog.Message + "<hr />")
   Next
 End Sub
End Class

Logging of unhandled errors to text file or database

On the same way, we can use Application_Error in Global.asax to write error message to text file or in some table in database. In this example, Application_Error procedure contains a code that writes error information to .txt file.

[ C# ]

void Application_Error(object sender, EventArgs e)
{
  // Get current exception
  Exception CurrentException;
  CurrentException = Server.GetLastError();
 
  // Write error to text file
  try
  {
    string LogFilePath = Server.MapPath("ErrorLog.txt");
    StreamWriter sw = new StreamWriter(LogFilePath);
    // Write error to text file
    sw.WriteLine(CurrentException.ToString());
    sw.Close();
  }
  catch (Exception ex)
  {
    // There could be a problem when writing to text file
  }
}

[ VB.NET ]

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
 
  ' Get current exception
  Dim CurrentException As Exception
  CurrentException = Server.GetLastError()
 
  ' Write error to text file
  Try
   
    Dim LogFilePath As String = Server.MapPath("ErrorLog.txt")
      
    Dim sw As System.IO.StreamWriter = _
      New System.IO.StreamWriter(LogFilePath)
    ' Write error to text file
    sw.WriteLine(CurrentException.ToString())
    sw.Close()
  Catch ex As Exception
    ' There could be a problem when writing to text file
  End Try
End Sub

Better error logging with Log4Net

If you simply write error details to text file you will get simple, but not scalable solution. In case of large number of concurrent users, text file could be locked for writing and you will get another error. Log4Net is more scalable solution for this problem. To find out how to use Log4Net see Using NHibernate and Log4Net in ASP.NET 2.0 applications tutorial.

How to send e-mail with error details

You can place a procedure for sending an email inside Application_Error, try-catch block or any other error handling code. Function to send email is pretty simple. In this example, code for sending notification e-mails is located in Application_Error procedure in Global.asax file. On this way e-mail will be sent whenever some undhandled error occurs.

[ C# ]

<%@ Application Language="C#" %>

<%
-- We need these namespaces to send e-mail --%>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Net.Mail" %>

<script runat="server">
 
void Application_Error(object sender, EventArgs e)
{
    // Get current exception
    Exception CurrentException = Server.GetLastError();
    string ErrorDetails = CurrentException.ToString();
 
    // Send notification e-mail
    MailMessage Email =
        new MailMessage("admin@yoursite.com",
        "admin@yoursite.com");
    Email.IsBodyHtml = false;
    Email.Subject = "WEB SITE ERROR";
    Email.Body = ErrorDetails;
    Email.Priority = MailPriority.High;
    SmtpClient sc = new SmtpClient("localhost");
    sc.Credentials =
        new NetworkCredential("EMailAccount", "Password");
    sc.Send(Email);
}   
      
</script>

[ VB.NET ]

<%@ Application Language="VB" %>
 
<%-- We need these namespaces to send e-mail --%>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Net.Mail" %>
 
<script runat="server">
       
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
    ' Get current exception
    Dim CurrentException As Exception = Server.GetLastError()
    Dim ErrorDetails As String = CurrentException.ToString()
 
    ' Send notification e-mail
    Dim Email As MailMessage = _
        New MailMessage("admin@yoursite.com", _
        "admin@yoursite.com")
    Email.IsBodyHtml = False
    Email.Subject = "WEB SITE ERROR"
    Email.Body = ErrorDetails
    Email.Priority = MailPriority.High
    Dim sc As SmtpClient = New SmtpClient("localhost")
    sc.Credentials = _
    New NetworkCredential("EMailAccount", "Password")
    sc.Send(Email)
End Sub
      
</script>

Handling errors with custom HttpModule

Custom Http module advantage is that module doesn't require changes in your web application code. Http module will catch the same event like Application_Error procedure. To create custom Http Module, start new project in Visual Studio. Project type should be Class Library. Add code like this:

[ C# ]

using System;
using System.Web;
 
namespace CommonModules
{
public class ErrorHandlingModule : IHttpModule
{
 
  public void Init(HttpApplication app)
  {
    app.Error += new EventHandler(this.HandleErrors);
  }
 
  public void HandleErrors(object o, EventArgs e)
  {
    // Get current exception
    Exception CurrentException = ((HttpApplication)o).Server.GetLastError();
 
    // Now do something with exception with code like in examples before,
    // send e-mail to administrator,
    // write to windows EventLog, database or text file
  }
 
  public void Dispose()
  {
    // We must have this procedure to implement IHttpModule interface
  }
}
}


[ VB.NET ]

Imports System
Imports System.Web
 
Namespace CommonModules
Public Class ErrorHandlingModule
  Implements IHttpModule
 
  Public Sub Init(ByVal app As HttpApplication)
    app.Error += New EventHandler(this.HandleErrors)
  End Sub
 
  Public Sub HandleErrors(ByVal o As Object, ByVal e As EventArgs)
    ' Get current exception
    Dim CurrentException As Exception = (CType(o, _
     HttpApplication)).Server.GetLastError()
 
    ' Now do something with exception with code like in examples before,
    ' send e-mail to administrator,
    ' write to windows EventLog, database or text file
  End Sub
 
  Public Sub Dispose()
    ' We must have this procedure to implement IHttpModule interface
  End Sub
End Class
End Namespace

To use the module in web application, you need to add few lines in Web.Config file.

<httpModules>
  <add name="ErrorHandlingModule" type="CommonModules.ErrorHandlingModule, CommonModules "/>
</httpModules>

More about how to create and implement custom Http modules in ASP.NET see in How To Create Your Own Http Module tutorial.

ASP.NET Error Handling Remarks

Be careful to handle possible errors in your Application_Error procedure. This procedure is executed when every error occurs, so Application_Error will call itself and it is possible to go in to infinite loop.

Writing error logs to text file can cause a problem with concurrency if a lot of errors need to be logged simultaneously. To make this task easier, you can use Log4Net. Also, there is pretty nice complete solution called Elmah now available at Google code.


Tutorial toolbar:  Tell A Friend  |  Add to favorites  |  Feedback  |   Google