Now it is time to put everything together into a useful HttpModule. The HttpModule implemented in this chapter is a module to log all unhandled errors to a file. If the log file exceeds a certain size , an event is raised. You then can resize or delete the log file with an event handler implemented in the Global.asax file. This module logs the time of the error, the error message, and the filename, including the line number that generated the error. The event raised in the Global.asax file contains extra data in a class derived from the System.EventArgs class. This HttpModule will read its initialization data from either the web.config file or the machine.config file. The initialization data contains the filename, including the path of the file where the log data is to be stored and the maximum size of the log file. You need to add the entries in Listing 25.5 to the beginning of your web.config file inside the <configuration> section. Listing 25.5 XML Configuration Entries for the machine.config or the web.config File<configSections> <section name="ErrorLogSettings" type="System.Configuration.NameValueFileSectionHandler, System" /> </configSections> <ErrorLogSettings> <add key="ErrorLogFile" value="c:\ErrorLog\Error.log" /> <add key="MaxFileSize" value="102400" /> </ErrorLogSettings> If you place the entries in the machine.config file instead, the <section> definition should go in the existing <configSections> section. The entries in Listing 25.5 provide data to the HttpModule about where the log file should be located and what the maximum size should be. The entry in the <configSections> section defines a new section for the configuration file. This definition includes the name of the class used to parse the section data. In this HttpModule, I used a standard parser class called NameValueFileSectionHandler . This parser class reads in name-value pairs of data. These name-value pairs can be accessed by a call to the GetConfig static method of the System.Configuration.ConfigurationSettings class. You also must add the following entry to the <HttpModules> section of either your machine.config or web.config file to register the module. This assumes that you build an assembly called ErrorLoggerCS. <add name="ErrorLogger" type="ErrorLoggerCS.ErrorLogModule,ErrorLoggerCS" /> Because this example is implemented in both C# and Visual Basic .NET, there are actually two assemblies. The C# assembly is called ErrorLoggerCS and the Visual Basic .NET assembly is called ErrorLoggerVB . Listing 25.6 is the complete C# source code for this HttpModule. Listing 25.7 is the Visual Basic .NET implementation of the same HttpModule. Listing 25.6 C# Code for Error-Logging HttpModuleusing System; using System.IO; using System.Web; using System.Configuration; using System.Collections.Specialized; namespace ErrorLoggerCS { /// <summary> /// Contains the data for the ErrorLogFull event that will /// be handled in the Global.asax file. /// </summary> public class ErrorLogEventArgs : EventArgs { //Private class members private string m_sFilename; private long m_nFileSize; private long m_nMaxSize; // Property accessors public string Filename { get { return m_sFilename; } set { m_sFilename = value; } } public long FileSize { get { return m_nFileSize; } set { m_nFileSize = value; } } public long MaxSize { get { return m_nMaxSize; } set { m_nMaxSize = value; } } // Constructor public ErrorLogEventArgs(string sFilename,long nFileSize,long nMaxSize) { m_sFilename=sFilename; m_nFileSize=nFileSize; m_nMaxSize=nMaxSize; } } /// <summary> /// Logs unhandled errors to a file. /// </summary> // Delegates for events that are to be handled in the global.asax file public delegate void ErrorLogFullHandler(object sender, EventArgs e); public class ErrorLogModule : IHttpModule { // Events that can be handled in the global.asax file public event ErrorLogFullHandler ErrorLogFull; //Private class members private string m_sLogFile=""; private long m_nMaxFileSize=0; // Constructor public ErrorLogModule() { } // Implement IHttpModule Methods public void Init(HttpApplication context) { context.Error += new EventHandler(OnError); // Load Setting information NameValueCollection objConfigData= ConfigurationSettings.GetConfig("ErrorLogSettings") as NameValueCollection; if(objConfigData!=null) { string sMaxFileSize=""; m_sLogFile=objConfigData["ErrorLogFile"]; sMaxFileSize=objConfigData["MaxFileSize"]; if(sMaxFileSize.Length==0 ) m_nMaxFileSize=Convert.ToInt64(sMaxFileSize); else m_nMaxFileSize=102400; //100K bytes if(m_sLogFile.Length==0) m_sLogFile=@"c:\Errors.log"; } else { m_sLogFile=@"c:\Errors.log"; m_nMaxFileSize=102400; //100K bytes } } public void Dispose() { } public void OnError(object sender, EventArgs args) { // Declare variables HttpApplication app; Exception objError; string sDateTime; string sErrorMessage; string sErrorLocation; int nStart,nEnd; FileInfo objFile; StreamWriter objWriter; try { app = sender as HttpApplication; objError=app.Context.Error.InnerException; sDateTime=DateTime.Now.ToString(); sErrorMessage=objError.Message; sErrorLocation=objError.StackTrace; nStart=sErrorLocation.IndexOf("in ")+3; nEnd=sErrorLocation.IndexOf("\r\n"); if(nEnd>nStart) sErrorLocation=sErrorLocation.Substring(nStart,nEnd-nStart); else sErrorLocation=sErrorLocation.Substring(nStart); //Open File objFile=new FileInfo(m_sLogFile); objWriter=objFile.AppendText(); //Write Data objWriter.Write(sDateTime); objWriter.Write("\t"); objWriter.Write(sErrorMessage); objWriter.Write("\t"); objWriter.Write(sErrorLocation); objWriter.Write("\r\n"); objWriter.Close(); // Check file size. If too large then raise event. objFile.Refresh(); if(objFile.Length>m_nMaxFileSize) { if(ErrorLogFull!=null) { ErrorLogFull(this, (EventArgs)(new ErrorLogEventArgs(m_sLogFile, objFile.Length,m_nMaxFileSize))); } } } catch(Exception e) { } } } } Listing 25.7 VB Code for Error-Logging HttpModuleImports System.Collections.Specialized Imports System.IO Namespace ErrorLoggerVB Public Class ErrorLogEventArgs Inherits EventArgs 'Private class members Private m_sFilename As String Private m_nFileSize As Long Private m_nMaxSize As Long ' Property accessors Public Property Filename() As String Get Return m_sFilename End Get Set(ByVal Value As String) m_sFilename = Value End Set End Property Public Property FileSize() As String Get Return m_nFileSize End Get Set(ByVal Value As String) m_nFileSize = Value End Set End Property Public Property MaxSize() As Long Get Return m_nMaxSize End Get Set(ByVal Value As Long) m_nMaxSize = Value End Set End Property ' Constructor Public Sub New(ByVal sFilename As String, ByVal nFileSize As Long, ByVal nMaxSize As Long) m_sFilename = sFilename m_nFileSize = nFileSize m_nMaxSize = nMaxSize End Sub End Class Public Class ErrorLogModule Implements IHttpModule 'Private class members Private m_sLogFile As String Private m_nMaxFileSize As Long ' Implement the IHttpModule interface. Public Sub Init(ByVal context As HttpApplication) Implements IHttpModule.Init AddHandler context.Error, AddressOf OnError 'Load Setting information Dim objConfigData As NameValueCollection objConfigData = ConfigurationSettings.GetConfig("ErrorLogSettings") If objConfigData Is Nothing Then m_sLogFile = "c:\Errors.log" m_nMaxFileSize = 102400 Else Dim sMaxFileSize As String m_sLogFile = objConfigData.Item("ErrorLogFile") sMaxFileSize = objConfigData.Item("MaxFileSize") If sMaxFileSize.Length = 0 Then m_nMaxFileSize = Convert.ToInt64(sMaxFileSize) Else m_nMaxFileSize = 102400 '100K bytes End If If m_sLogFile.Length = 0 Then m_sLogFile = "c:\Errors.log" End If End If End Sub Public Sub Dispose() Implements IHttpModule.Dispose End Sub ' Implement event to be handled in Global.asax file Event LogUnhandledError(ByVal sender As Object, ByVal e As EventArgs) ' Implement the event handlers Public Sub OnError(ByVal sender As Object, ByVal e As EventArgs) 'Declare variables Dim app As HttpApplication Dim objError As Exception Dim sDateTime As String Dim sErrorMessage As String Dim sErrorLocation As String Dim nStart, nEnd As Integer Dim objFile As FileInfo Dim objWriter As StreamWriter Try app = sender objError = app.Context.Error.InnerException sDateTime = DateTime.Now.ToString() sErrorMessage = objError.Message sErrorLocation = objError.StackTrace nStart = sErrorLocation.IndexOf("in ") + 3 nEnd = sErrorLocation.IndexOf(Chr(13) + Chr(10)) If nEnd > nStart Then sErrorLocation = sErrorLocation.Substring(nStart, nEnd - nStart) Else sErrorLocation = sErrorLocation.Substring(nStart) End If 'Open File objFile = New FileInfo(m_sLogFile) objWriter = objFile.AppendText() 'WriteData objWriter.Write(sDateTime) objWriter.Write(Chr(9)) objWriter.Write(sErrorMessage) objWriter.Write(Chr(9)) objWriter.Write(sErrorLocation) objWriter.Write(Chr(13) + Chr(10)) objWriter.Close() 'Check file size. If too large then raise event objFile.Refresh() If objFile.Length > m_nMaxFileSize Then Dim objEventArgs As ErrorLogEventArgs objEventArgs = New ErrorLogEventArgs(m_sLogFile, objFile.Length, m_nMaxFileSize) RaiseEvent LogUnhandledError(Me, objEventArgs) End If Catch End Try End Sub End Class End Namespace |