I have the following in my Global.aspx which is meant for handling errors:
void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.
Application_Error block can catch exception anytime between application life cycle.
Application life cycle is parent of Session life cycle as you can understand there can be many sessions within a single application.
Thus you may have HttpContext.Current null at certain errors occured before creating session or after expiring of sessions.
If you want to write session specific error redirects you should check for Null of current HttpContext always.
You can also use Server.GetLastError to know the error details occured and write your error page redirect through CustomError tag in web.config
See the following link
http://weblogs.asp.net/scottgu/archive/2006/08/12/Tip_2F00_Trick_3A00_-Show-Detailed-Error-Messages-to-Developers.aspx
Application Errors can occur at any time - including when no connection is present.
For example, if a background thread is processing and causes an exception.
Block Level
This is the most granular level of exception handling in applications. We are very familiar with try-catch blocks that we can wrap over a set of code and if an exception occurs then it will handle this exception. The exception handling block is like this.
try
{
throw new InsufficientMemoryException();
}
catch (Exception ex)
{
throw new Exception("");
}
catch
{
throw;
}
Since this is not a basic exception handling article, we will not go deepper into that example.
Page Level
We can implement an exception handling mechanism at the page level. The advantage is that we do not need to wrap all our code within the try-catch-finally block; we can say that, this is centralizing the exception handling mechanism of a page. Wherever exception bubbles up, it will catch by following code.
void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
}
To determine the Exception type we need to use the GetLastError() function of the Server class that will return the exception type object and by checking this object we can make further decisions, whether to handle the exception within this page or throw it to a higher level. If a higher level then what higher level?
Application Level
Yes, this is the top level of the exception handle mechanism. If we implement it in the Global.asax page. We all are familiar with the Global.asax page that mostly deals with the Global (application) and session related objects. If we implement the Application_Error() event within this page then all unhandled exceptions will stack here and we can make a supreme decision about the error. Whether we will ignore it or log it or send it in mail. Here is the implementation of Application_Error() in a Global.asax page.
protected void Application_Error(object sender, EventArgs e)
{
//Catch Exception in Central place
Exception exceptionObject = Server.GetLastError();
}
The Exception detection mechanism is very similar to the Page Level exception handling mechanism. We are using the GetLastError() function of the Server class that will return one exception type object. Now, it’s our duty to investigate the exception type further and the possible solution for it.
Fine, we have seen the three levels of the exception handling mechanism in ASP.NET applications. Now, the obvious question is, shall we implement all those levels in a single application? Why not? They can peacefully adjust themselves within the same application and moreover they work like a team. If one fails to handle an exception then the other tries. If again it fails then its higher authority tries, like this.
Fine, the next question is if the bottom level is able to solve the exception? Will it call to the higher level? No, if the lower level is capable of handling an exception then it will not bubble up (call) an exception to its higher level. Let’s clear up the concept.
In one ASP.NET page I have written this code.
try
{
throw new DivideByZeroException();
}
catch (DivideByZeroException ex)
{
}
catch
{
throw;
}
Where we are throwing a DivideByZero Exception from a try block and next to that we are catching it by passing a proper Exception object type. So the catch block can handle the exception. Now make the situation a bit more complex. Within this page we will keep the following code for the global exception handling in the page level.
void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
}
And we will see that the code will not execute at the time of the exception handling. Because the native try-catch block is sufficient to handle the exception, no need to call its superior mechanism and for the same reason the Application Level exception mechanism will be skipped, if any. Fine, so far we have learned the levels of the exception mechanism and clarified a few concepts of it. We will now implement all those levels in one sample application and we will fulfill our goal. Let’s proceed step-by-step.
Step 1: Create exception in block level and wrap with try-catch
The step is pretty simple and we have done it many times. Within a try block we are throwing an InsufficientMemoryException and we are assuming that this try block will throw “DivideByZeroException” , if our assumption is right then we can handle this exception otherwise we will throw it to a higher level.
try
{
throw new InsufficientMemoryException();
}
catch (DivideByZeroException ex)
{
//show Message
}
catch
{
throw;
}
Where is the higher level mechanism? The page level. We will implement it in the next step.
Step 2: Implement exception handling mechanism in page level
Here is the next level of exception handling. We have implemented a Page_Error() event that can capture all unhandled exceptions within this page. Now, we are expecting this page to only throw an ObjectDisposeException and a little bit optimistically we have kept the mechanism to handle only this type of exception. (That is a very silly implementation, we should not do that.). Anyway, if the exception is any other type then we will throw it to a higher handling mechanism.
void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex is ObjectDisposedException)
{
//Log this Exception
}
else
throw new HttpUnhandledException("Unhandle Exception", ex);
}
The next higher authority is the Application Level exception handling mechanism.
Step 3: Implement Application_Error() in Global.asax page
protected void Application_Error(object sender, EventArgs e)
{
//Catch Exception in Global place
Exception exceptionObject = Server.GetLastError();
try
{
if (exceptionObject != null)
{
if (exceptionObject.InnerException != null)
{
exceptionObject = exceptionObject.InnerException;
}
switch (exceptionObject.GetType().ToString())
{
case "System.Threading.ThreadAbortException":
HttpContext.Current.Server.ClearError();
break;
default:
LogException(exceptionObject);//Custom method to log error
break;
}
}
}
catch { }//Avoiding further exception from exception handling
}
And the LogException() function is a stub for implementing much more stuff by going beyond our core explanation. Here it is.
public static void LogException(Exception ex)
{
//Log my Exception
}