|
||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIt's always been a problem to handle exceptions in a large enterprise environment, where you want to deal with different exceptions in a different manner. Though error pages can be configured in the web.config, but for only HTTP-specific errors. You cannot define specific Exception types with their respective handlers. One solution that I found on the net was Exceptions Management Block. But that was after all a complex solution according to me. So I devised my own mechanism to configure Exception types with their respective handlers in web.config. Problem DefinitionNormally, in a simple application, we deal with exceptions in a Try
// Do some code here
Catch sqle as SQLExceptions
// Handle SQLException differently
Catch e as Exceptions
// Handle Generic Exception differently
End Try
This is fine for a simple application, but for an enterprise application where several pages can raise exceptions, it can cause a headache to configure each of these blocks individually. Also, if you have derived your own application-specific exceptions, you have to handle them separately, and if you want to make any change in handling exceptions, you have to dive into your aspx pages. Proposed SolutionTo overcome this problem, I have defined a custom configuration section, that defines exception type, with its error-handler (assembly and class) and redirect-URL. In this way, you can configure an exception, its handler (both assembly and class) and redirect URL without intervening into your previously written code, in an independent manner. Configuring And Handling ExceptionsFirst of all, we have to define a custom configuration section in web.config, just below <configSections >
<section name="exceptionManagers"
type="ExceptionManagers.ExceptionManagersHandler,ExceptionManagers" />
</configSections>
And just before ending <exceptionManagers>
<exceptionManager application="MyApplication">
<exceptions>
<exception name="System.SQLException" url="ErrorPage.aspx">
<exceptionHandler assembly="ExceptionManagers"
name="SQLExceptionHandler" />
</exception>
</exceptions>
</exceptionManager>
<exceptionManager application="MyApplication">
<exceptions>
<exception name="System.InvalidOperationException"
url="ErrorPage.aspx">
<exceptionHandler assembly="ExceptionManagers"
name="InvalidOperationExceptionHandler" />
</exception>
</exceptions>
</exceptionManager>
</exceptionManagers>
The above section defines an exception of type Try
//Do Some Code here , that raises Exception
Catch sqle as SQLException
Response.Redirect( ExceptionManagersHandler.PublishException("MyApplication",_
sqle) )
Catch exc as Exception
Response.Redirect(ExceptionManagersHandler.PublishException("MyApplication",_
exc) )
End Try
This line simply calls a shared method Using the codeTo define the exception handlers, create a class library project and name it ExceptionManagers (which is the assembly name in ' This Class implements the IConfigurationSectionHandler interface and
' reads the configuration settings and returns a hashtable based on the
' current settings in web.config
Option Strict On
Imports System
Imports System.Collections
Imports System.Xml
Imports System.Configuration
Imports System.Reflection
Public Class ExceptionManagersHandler
Implements IConfigurationSectionHandler
'This method reads the configuration section of the
'web.config and returns a hashtable
'populated with all the information od exceptions and their handlers
' Hashtable contains ExceptionInfo class's objects
Public Function Create(ByVal parent As Object, _
ByVal configContext As Object, ByVal section As XmlNode) _
As Object Implements IConfigurationSectionHandler.Create
Dim _HandlerBucket As New Hashtable()
Dim appName, exceptionName, redirectUrl, _
errorHandler, assemblyName As String
Dim managerNode, exceptionNode, handlerNode As XmlNode
Dim managersNL, exceptionsNL, handlersNL As XmlNodeList
Dim exceptionsList As Hashtable
Dim excepInfo As ExceptionInfo
managersNL = section.SelectNodes("//exceptionManager")
For Each managerNode In managersNL
appName = managerNode.Attributes.GetNamedItem("application").Value
exceptionsNL = managerNode.SelectNodes("exceptions/exception")
For Each exceptionNode In exceptionsNL
exceptionsList = New Hashtable()
exceptionName = _
exceptionNode.Attributes.GetNamedItem("name").Value
redirectUrl = _
exceptionNode.Attributes.GetNamedItem("url").Value
excepInfo = _
New ExceptionInfo(appName, exceptionName, redirectUrl)
handlersNL = exceptionNode.SelectNodes("exceptionHandler")
For Each handlerNode In handlersNL
assemblyName = _
handlerNode.Attributes.GetNamedItem("assembly").Value
errorHandler = _
handlerNode.Attributes.GetNamedItem("name").Value
Next
excepInfo.HandlerAssembly = assemblyName
excepInfo.HandlerName = errorHandler
exceptionsList.Add(exceptionName, excepInfo)
Next
_HandlerBucket.Add(appName, exceptionsList)
Next
Return _HandlerBucket
End Function
' This method is called in all the catch blocks of your application
' It returns a URL back to the calling application
Public Shared Function PublishException(ByVal appName As String, _
ByVal e As Exception) As String
If (appName Is Nothing) Then
appName = "GenericAppication"
End If
Dim expName As String = e.GetType.ToString
' Read the congiuration hashtable
Dim handlerBucket As Hashtable = _
CType(System.Configuration.ConfigurationSettings.GetConfig("exceptionManagers"),_
Hashtable)
'Find , is an appropriate handler is available for
'the application that raised exception
Dim exceptionHT As Hashtable = _
CType(handlerBucket.Item(appName), Hashtable)
Dim excepInfo As ExceptionInfo
If Not (exceptionHT Is Nothing) Then
' If application hashtable is not empty,
' then find the raised exception by name
excepInfo = CType(exceptionHT.Item(expName), ExceptionInfo)
Dim assemName, className As String
Dim classType As Type
Try
' Load the Assembly
assemName = excepInfo.HandlerAssembly
className = assemName & "." & excepInfo.HandlerName
Dim assem As [Assembly] = [Assembly].Load(assemName)
' Load the handler class
classType = assem.GetType(className)
Dim objref As Object = Activator.CreateInstance(classType)
' Cast the object to its interface, so that all exceptions
' can be published by a single call
' i have used command pattern here
Dim handler As IExceptionHandler = _
CType(objref, IExceptionHandler)
handler.executeHandler(e)
Catch exp As Exception
throw new Exception ("Unknown Exception Occured " & _
"in loading or instantiating handler" & exp.Message)
End Try
End If
Return excepInfo.RedirectUrl
End Function
End Class
The code for ' IExceptionHandler Interface
Public Interface IExceptionHandler
Sub executeHandler(ByVal except As Exception)
End Interface
'ExceptionInfo class , that is populated with the information in the web.config
Public Class ExceptionInfo
'Mandatory Fields
Private _ExceptionName As String
Private _RedirectUrl As String
Private _ApplicationName As String
'Optional Fields
Private _HandlerName As String
Private _HandlerAssembly As String
Public Sub New(ByVal applicationName As String, ByVal _
exceptionName As String, ByVal errorUrl As String)
_ApplicationName = applicationName
_ExceptionName = exceptionName
_RedirectUrl = errorUrl
End Sub
Public ReadOnly Property ExceptionName() As String
Get
Return _ExceptionName
End Get
End Property
Public ReadOnly Property RedirectUrl() As String
Get
Return _RedirectUrl
End Get
End Property
Public ReadOnly Property ApplicationName() As String
Get
Return _ApplicationName
End Get
End Property
Public Property HandlerName() As String
Get
Return _HandlerName
End Get
Set(ByVal Value As String)
_HandlerName = Value
End Set
End Property
Public Property HandlerAssembly() As String
Get
Return _HandlerAssembly
End Get
Set(ByVal Value As String)
_HandlerAssembly = Value
End Set
End Property
End Class
ConclusionHandling exceptions in such way gives a user ability to write the exception handling code outside the Points of InterestI used 'Command Pattern' with reflection to implement an exception handling mechanism that is independent of using the application. I do feel fun to play with patterns, though I know much less about them.
|
|||||||||||||||||||||||||||||||||||||||||||||||