Community Pick: Many members of our community have endorsed this article.
Editor's Choice: This article has been selected by our editors as an exceptional contribution.

Exception Handling: A Mechanism to Effectively Manage Errors in .Net

Ritesh RatnaBusiness Analyst/SharePoint Consultant
Published:

Prologue

In some discussion forum or a blog that I read, the author claimed that he had written an error-free application. Now, this is a very controversial statement which is bound to raise eyebrows... However, what the author was actually claiming was that his application did not throw any unhandled errors. He was simply claiming that his application would not crash under any circumstances.

Now, writing an application that does not crash is neither a Magic nor a Rocket Science. We all can do that, the only thing we need is a clear understanding of what an Error is and carefully designing our application to handle all the Expected and Unexpected Errors.

However, it is also important to note, we can write and devise mechanisms to handle errors in our applications, but there will always be a possibility of having bugs and defects. Now then, what is the difference between an error and a bug?


ERROR vs. BUG

Bug – It is a condition or an event where an application behaves in an unpredictable manner. The output or the logic built in the application does not accurately comply with the stipulated requirements for the application.

Most bugs arise from mistakes and errors made by people in either a program's source code or its design, and a very few are caused by compilers producing incorrect code.

It differs from an Error in the way that without any special handling mechanism, the application continues to execute without crashing.

Error – It is the incorrect output or a condition when the application is not able to execute as expected or as per the built in logic.

It differs from a Bug in the way that without a handling mechanism, it would cause the application to crash.

So, what I intend to say is that we cannot guarantee that our programs will not have errors and issues. We cannot avoid the Bugs.  However, what we can we can make sure is, that all the errors in our application have an efficient handling mechanism, in order to prevent the application from crashing during execution.


What is an Exception?

An Exception is any error condition or unexpected behavior or disruption in the expected execution of a program. It is any occurrence or event that causes the execution of the program to fail, or produces an output that is unacceptable and unexpected as per the programed logic or the requirement.

Exceptions can be raised because of a fault in the code or in code of a shared library, unavailable operating system resources, unexpected conditions that the common language runtime encounters (such as code that cannot be verified), and so on.


Causes of Exceptions:

Broadly speaking, there are three different situations that cause exceptions to be thrown:

Exceptions due to programming errors:
These are the exceptional conditions that arise due to the programming errors.
E.g. NullPointerException and IllegalArgumentException

Exceptions due to client code errors:
The program attempts to do something that is not allowed by the API, and thereby violates its contract.
E.g. An integer division operation throws a DivideByZeroException if the denominator is zero.
Exceptions due to resource failures:
These are the exceptions that are generated when the resources fail.
E.g. The system runs out of memory or a network connection fails. This causes the execution of the application to a breaking point.
Exceptions due to incorrect logic:
These exceptions are generated due to the incorrect implementation of the logic.
E.g. A throw statement throws an exception immediately and unconditionally. Control never reaches the statement immediately following the throw.

Standard Exceptions

If we talk in reference to the .NET Framework, an exception is an object that inherits from the Exception Class. When an exception is thrown from an area of code where a problem has occurred, it is passed up the stack until the application handles it or the program terminates. All the Exceptions thrown by .NET runtime have their base class as Exception.

In C# almost all (though not all) inherit either from the System.Exception or the ApplicationException base class. These two classes form the basis for most of the runtime exceptions.

The common language runtime throws SystemException, while the ApplicationException is thrown by a user program rather than the runtime. The SystemException includes the ExecutionEngineException, StackOverFlowException etc. It is generally not recommended to catch SystemExceptions also it is not good programming practice to throw SystemExceptions in applications. The exceptions that are derived directly from System.Exception include IOException, WebException etc.

Based on the above understanding, the Exceptions can be categorized into two types:

1)  Exceptions generated by an executing program
     (These exception classes are derived from the SystemException class)
2)  Exceptions generated by the common language runtime
     (These exception classes are derived from the ApplicationException class)

Some of the Exception Classes or we may say the Standard Exceptions thrown by the .NET runtime are:

System.OutOfMemoryException
Thrown when an attempt to allocate memory (via new) fails.
System.NullReferenceException
Thrown when a null reference is used in a way that causes the referenced object to be required.
System.InvalidCastException
Thrown when an explicit conversion from a base type or interface to derived types fails at run time.
System.ArrayTypeMismatchException
Thrown when a store into an array fails because the actual type of the stored element is incompatible with the actual type of the array.
System.IndexOutOfRangeException
Thrown when an attempt to index an array via an index that is less than zero or outside the bounds of the array.
System.ArithmeticException
A base class for exceptions that occur during arithmetic operations, such as System.DivideByZeroException
System.DevideByZeroException
Thrown when an attempt to divide an integral value by zero occurs.
System.OverFlowException
Thrown when an arithmetic operation in a checked context overflows.
System.MulticastNotSupportedException
Thrown when an attempt to combine two non-null delegates fails, because the delegate type does not have a void return type.
System.TypeInitializationException
Thrown when a static constructor throws an exception and no Catch clauses exists to catch in.

Exception Type Features

Exception types support the following features:

Human-readable text that describes the error. When an exception occurs, the runtime makes available a text message to inform the user of the nature of the error and to suggest action to resolve the problem. This text message is held in the Message property of the exception object. During the creation of the exception object, you can pass a text string to the constructor to describe the details of that particular exception. If no error message argument is supplied to the constructor, the default error message is used.
The state of the call stacks when the exception was thrown. The StackTrace property carries a stack trace that can be used to determine where in the code the error occurs. The stack trace lists all the called methods, and the line numbers in the source file where the calls are made.

Exception Class Properties

Exception includes a number of properties that help identify the code location, the type, the help file, and the reason for the exception: StackTrace, InnerException, Message, HelpLink, HResult, Source, TargetSite, and Data.
When a causal relationship exists between two or more exceptions, the InnerException property maintains this information. The outer exception is thrown in response to this inner exception. The code that handles the outer exception can use the information from the earlier inner exception to handle the error more appropriately. Supplementary information about the exception can be stored in the Data property.
The error message string passed to the constructor during the creation of the exception object should be localized, and can be supplied from a resource file using the ResourceManager. For more information on localized resources, see the System.Resources namespace overview and Packaging and Deploying Resources.
To provide the user with extensive information concerning why the exception occurred, the HelpLink property can hold a URL (or URN) to a help file.
Exception uses the HRESULT COR_E_EXCEPTION, which has the value 0x80131500.

User-Defined Exceptions

In C#, we can create our exception class (user defined); by inheriting our class from the Exception base class or one of its standard derived classes.

using System;
                      using System.Collections.Generic;
                      using System.Linq;
                      using System.Web;
                      using System.Web.UI;
                      using System.Web.UI.WebControls;
                      using System.Web.Security;
                      
                      namespace TestApplication
                      {
                          public partial class _Default : System.Web.UI.Page
                          {
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  try
                                  {
                                      Response.Write("Try Block .............. <BR>");
                      
                                      //Throwing a User Defined Exception    
                                      throw new MyException("I am throwing an exception");
                                  }
                                  catch (MyException ex) 
                                  {
                                      Response.Write("Catch Block .............. " + ex.Message + "<BR>" + ex.Msg);
                                  }
                                  finally
                                  {
                                      Response.Write("Finally Block ............. <BR>");
                                  }
                              }
                          }
                          
                          //User Defined Exception    
                          public class MyException : SystemException
                          {
                              public string Msg;
                              
                              public MyException(string str):base(str)
                              {
                                  Msg = str + "I am inside MyException <BR>";
                              }
                          }
                      
                      }

Open in new window



What is Exception Handling? And...
Why do we need Exception Handling?

Life is unpredictable, we could only plan it; still it always has unforeseen surprises every now and then.
This philosophy holds true in software development also. The Errors/Exceptions in an application can only be avoided by careful Software Analysis & Design and all kinds of Testing. Still there will always be a strong possibility that we might have missed something.

If we accept and believe in the above philosophy, then we need to prepare our application to handle such situations at any time; this is ‘Exception Handling’.

Now the question is how we do it. The simplest way would be to write a piece of code which will be called when an exception occurs, this piece of code is called, an ‘Exception Handler’.

As a programmer, even I always had a tendency to concentrate more towards the core functionality and, giving less effort to the handling of the exceptions. But now I realize and always emphasize that catching and handling of runtime errors is one of the most important tasks that a programmer should always keep in mind and put all efforts into while developing an application.

As I read somewhere; “The mark of a good, robust program is planning for the unexpected, and recovering if it does happen”. Errors can happen at almost any time during the execution of a program. We can detect and deal with these errors using Exception Handling.

Moreover, if the Exceptions are left unhandled, the ASP.NET displays an exception stack trace which reveals a part of the code and how it works. This information, if it gets into the hands of a hacker, may have serious security consequences. Hence the need of effective exception handling becomes even more important.

There might be various reasons to handle exception; this can be caused due to improper user inputs, improper design logic or system errors. In this scenario, if application does not provide a mechanism to handle these anomalies then there might be cases the application may crash. .NET run time environment provide a default mechanism, which terminates the program execution.

.NET framework has an in-built mechanism in to detect and handle run time errors. The .NET framework contains lots of standard exceptions. It allows you to define how the system reacts in unexpected situations like 'File not found', 'Out of Memory’, bad logic, non-availability of operating system resources other than memory, 'Index out of bounds' and so on. When code which has a problem is executed, it raises an exception.  If a programmer does not provide a mechanism to handle these problems, the .NET run time environment provides a default mechanism, which terminates the program execution. This mechanism is a structured exception handling mechanism.

C# also provides a structured, and type-safe way of handling both system level and application level error conditions. The exception mechanism in C# is very similar to that of C++, with a few important differences.


Difference in Handling Exceptions in Web and Windows Application

In Windows desktop applications, the exception handling is quite different from handling exceptions for web applications.

Web Application
In web applications, we have an event Application_Error. This event handles all the exceptions that are not handled elsewhere in the application.
void Application_Error(object sender, EventArgs e)
                      { 
                          // Code that would be executed when an unhandled exception occurs
                      }

Open in new window

Windows Application
In the Widows Application, we have a class ‘Program.cs’.  Program class has a static method Main(). All the unhandled exceptions need to be handled in this method.
static void Main()
                      {
                          try
                          {
                              // Code that has a possibility of throwing an Exception while executing.
                          }
                          catch (Exception)
                          {
                              // Code that would be executed when an unhandled exception occurs
                          }
                      }

Open in new window


Exception Classes

C# is part of the Microsoft .NET Framework. C# does not have a type library of its own, but shares the .NET Framework class library with other .NET languages. The .NET class library provides a root class for exception handling: the Exception class in the System namespace. This class is the parent class of all exception classes.

            System.Exception

This System.Exception class has a number of useful properties.  One of them is Message property. This property gives you the error message text that you can display on the screen so that your user can report that back to you.

           catch (System.Exception ex)
                                  {
                                      Response.Write("Catch Block ............." + ex.Message + "<BR>");
                                  }

Open in new window

We will have a more detailed look at this System.Exception class later in our discussion.  For now, just understand that ‘System.Exception’ is a class, which has a property ‘message’ that stores the error message for the type of error.


How to do Exception Handling

There are three ways to handle exceptions/errors in ASP.NET:

1.  Structured Exception Handling (i.e. try-catch-finally block)
2.  Page Level and Application Level Error Event Handlers
3.  Custom Error Page

Structured Exception Handling (try-catch-finally block)

The .NET Framework has enhanced the ways in which you deal with errors. C#'s mechanism for handling error conditions, allows you to provide custom handling for each type of error condition, as well as to separate code that identifies errors from the code that handles them.

Exceptions in C# provide a structured and type-safe way of handling both system level and application level error conditions. The exception mechanism in C# is very similar to that of C++, with a few important differences.

In C#, all exceptions must be represented by an instance of a class type derived from System.Exception.

Try-Catch-Finally

The common language runtime provides an exception handling model that is based on the representation of exceptions as objects, and the separation of program code and exception handling code into Try blocks and Catch blocks, respectively. There can be one or more Catch blocks, each designed to handle a particular type of exception, or one block designed to catch a more specific exception than another block.

If an application handles exceptions that occur during the execution of a block of application code, the code must be placed within a Try statement. Application code within a Try statement is a Try block. Application code that handles exceptions thrown by a Try block is placed within a Catch statement, and is called a Catch block. Zero or more Catch blocks are associated with a Try block, and each Catch block includes a type filter that determines the types of exceptions it handles.
 
The Try block contains code where an error can occur. This block is executed until an exception is thrown.
   Rule
   -  try Block consist of code that might generate error.
   -  try Block must be associated with one or more catch block or by finally block.
   -  try Block need not necessarily have a catch Block associated with it but in that case it must have a finally Block associate with it.
The Catch block contains code to handle any error that does occur. This block catches the exception and executes the code written in the block. If we do not know what kind of exception is going to be thrown we can simply omit the type of exception i.e. the exception argument.
   Rule
   -  catch Block is used to recover from error generated in try Block.
   -  In case of multiple catch Block, only the first matching catch Block is executed.
   -  when you write multiple catch blocks you need to arrange them from specific exception type to more generic type.
   -  When no matching catch block is able to handle exception, the default behavior of web page is to terminate the processing of the web page.
The exception argument is an instance of the Exception class or an instance of a class that derives from the Exception class corresponding to the error that occurred in the Try block. The Exception class instance contains information about the error including, among other things, its number and message.
The Finally block is an optional block, it is always executed when execution leaves any part of the Try statement. This block contains all the cleanup code. It does not support the error message, but all the code contained in the Finally block is executed after the exception is raised. We can use this block along with Try...Catch and only with Catch too. The Finally block is executed even if the error is raised. Control is always passed to the Finally block regardless of how the Try blocks exits.
   Rule
   -  finally Block contains the code that always executes, whether or not any exception occurs.
   -  We should use finally block to write cleanup code. i.e. you can write code to close files, database connections, etc.
   -  Only One finally block is associated with try block.
   -  Finally block must appear after all the catch block.
   -  If there is a transfer control statement such as goto, break or continue in either try or catch block the transfer happens only after the code in the Finally block is executed.
   -  If you use transfer control statement in finally block, you will receive compile time error.
Note: Local variables from a Try block are not available in a Catch block because they are separate blocks. If you want to use a variable in more than one block, declare the variable outside the Try...Catch...Finally structure.

When an exception occurs in a Try block, the system searches the associated Catch blocks in the order they appear in application code, until it locates a Catch block that handles the exception. A Catch block handles an exception of type T if the type filter of the Catch block specifies T or any type that T derives from. The system stops searching after it finds the first Catch block that handles the exception. For this reason, in application code, a Catch block that handles a type must be specified before a Catch block that handles its base types, as demonstrated in the example that follows this section. A Catch block that handles System.Exception is specified last.

Once a matching Catch clause is found, the system prepares to transfer control to the first statement of the Catch clause. Before execution of the Catch clause begins, the system first executes, in order, any Finally clauses that were associated with Try statements more nested that than the one that caught the exception.

If no matching Catch clause is found, one of two things occurs:
If the search for a matching Catch clause reaches a static constructor or static field initializer, then a System.TypeInitializationException is thrown at the point that triggered the invocation of the static constructor. The inner exception of the System.TypeInitializationException contains the exception that was originally thrown.
If the search for matching Catch clauses reaches the code that initially started the thread, then execution of the thread is terminated. The impact of such termination is implementation-defined.

Exit Try

The legacy programmers always have a question at this point that, “How do we exit a Try block?”

Though we do have an Exit Try statement in VB .Net, but in C# there is no such mechanism. The simple reason being, ‘we do not want to break away from the Try block’. The only thing that we have in C#, nearest to and working similar to an Exit is ‘Label’.

However, still my personal opinion is:  It is better to throw an exception (instead of exit Try) and catch it somewhere and handle the rest in a Finally block.  Anyway, even in VB .Net if we have a Finally clause, Exit Try will jump to that rather than jumping out of the Try statement altogether. Hence why not handle the logic appropriately in Finally block, instead of using the Exit Try.

Catching Specific Exceptions

We can specify the type of system exceptions that we want to catch. The Catch block can take an object argument derived from System.Exception class, in which case it handles that specific exception.

Syntax

          catch (ExceptionType ExceptionObject)
            {
                  //Code that has to be excuted to handle the
                  //type of exception for which object is passed
                  //as argumnet.
            }


In .NET, all exceptions are derived from the Exception class. The Exception class is defined inside the System namespace. Other derived exception classes are spread across many other namespaces.

Here in the above syntax, the ExceptionType is any class derived from the ‘System.Exception’ and the ExceptionObject is the name of object created for that Exception Class i.e. the Type of Exception.

E.g.--

    try
                          {
                              object m = null;
                              string n;
                                      
                              Response.Write("Try Block ............." + "<BR>");
                              n = m.ToString();  
                          }
                          catch (System.NullReferenceException ex)
                          {
                              Response.Write("Catch Block                 .............NullReferenceException: " + ex.Message + "<BR>");
                          }
                                   
                          finally
                          {
                              Response.Write("Finally Block ............." +                 "<BR>");
                          }

Open in new window


Output
Try Block .............
Catch Block .............NullReferenceException: Object reference not set to an instance of an object.
Finally Block .............

In the above example we catch the Exception of Type System.NullReferenceException in an object we've named ex. Hence, if there is an exception of this Type, it will be caught by the Catch block.

Similarly, if we pass an argument of any other Exception Class of System.Exception Type in the Catch statement, it will catch all exceptions of the specified type and all types further derived from it.

Hence we see that, we do not need to catch all exceptions, we can specify only the expected exceptions. Which means, if we are doing an arithmetic calculation, we can handle ArithmeticException and DivideByZeroException and when we are accessing the web from our code, we can specifically handle HttpException. Though, this is not a thumb rule. The decision of which exception needs to be handled and which needs to be ignored, would depend on the business logic and the design of the application.

Some of the important and normally used Exception classes are listed above as Standard Exceptions.


Catching All Exceptions

A Catch statement handles an exception that is of the same type as the type of the receiving object in the Catch statement, or of a type derived from it.

Based on this understanding, we have two ways of catching all exceptions:

1)  Build a Catch block without specifying any Exception Class
Build a Catch block without a bracket or arguments. If we write a Catch statement that does not specify an exception type, it would handle any exception derived from the Exception class. Moreover, if such a statement is the last Catch statement, it would catch any exception that we did not handle in the preceding Catch blocks.
           
    try
                          {
                              // Code that has a possibility of throwing an Exception while executing.  
                          }
                          catch 
                          {
                              // Code that would be executed when an unhandled exception occurs.
                          }
                          finally
                          {
                              // Code that has to be excuted after the Exception handling.
                              // (this is an optional block)
                          }

Open in new window

2)  Build a Catch block with System.Exception Class
As already said, in .NET, all exceptions are derived from the System.Exception class. This Exception class is defined inside the System namespace. Other derived exception classes are spread across many other namespaces.

Since all exceptions are derived from the System.Exception class, if we catch System.Exception, that would cover all exceptions derived from System.Exception also. Hence, the statement ‘catch (Exception)’ would catch all exceptions of type System.Exception and all derived exceptions.
   try
                         {
                            // Code that has a possibility of throwing an Exception while executing.  
                         }
                         catch (System.Exception ex)
                         {
                            // Code that would be executed when an unhandled exception occurs.
                         }
                         finally
                         {
                            // Code that has to be excuted after the Exception handling.
                            // (this is an optional block)
                         }

Open in new window

Either way, the catch block ends up handling all exceptions.   But, my personal opinion is that, it is a bad practice to catch all exceptions. You should catch only specific exceptions which are expected in the specific code block.  For example, if you are attempting to allocate the memory, you may catch 'System.OutOfMemoryException' and if you are performing mathematical operations, you may catch ‘System.ArithmeticException’ and ‘System.DivideByZeroException’ etc. The bottom line is, depending on the nature of the code, you must handle the appropriate, specific exceptions, instead of catching the father of all exceptions (System.Exception).


Multiple Catch Blocks

A sequence of code in the Try block, may throw a number of different types of exceptions.  For instance, an arithmetic operation might throw a System.ArithmeticException or a System.DevideByZeroException.  At another point, the same sequence of code might throw System.OutOfMemoryException or a System.NullReferenceException. While conversion of types may have invalid casting or explicit conversion and might throw System.InvalidCastException.

In such a scenario, we need to properly and carefully handle all the possible exceptions arising in the same Try block, and hence we need multiple Catch blocks.

    try
                          {
                              // Code where exceptions are likely to occur.
                          }
                          catch (System.NullReferenceException ex)
                          {
                              // Code that has to be excuted to handle the NullReferenceException
                          }
                          catch (System.IndexOutOfRangeException ex)
                          {
                              // Code that has to be excuted to handle the IndexOutOfRangeException
                          }
                          catch (System.DivideByZeroException ex)
                          {
                              // Code that has to be excuted to handle the DivideByZeroException
                          }
                          catch (System.ArithmeticException ex)
                          {
                              // Code that has to be excuted to handle the ArithmeticException
                          }
                          catch (Exception ex)
                          { 
                               // Code that has to be excuted to handle the Generalised Exception
                          }
                          finally
                          {
                              // Code that has to be excuted after the Exception handling
                              // (this is an optional block)
                          }

Open in new window

As shown above, we can have any number of Catch blocks for each Try block.

When an exception occurs within a Try block, the program control will jump to the first Catch block and compare if the exception type is same as the type specified in the Catch block. If the type matches, it will execute the Catch block. If the types do not match, it will jump to the next Catch block and compare. Like this, it will compare against all Catch blocks until a match is found. If there is no Catch block found which matches the exception type, it will become an unhandled exception and will lead to program termination. Hence the thumb rule is to “Catch derived exceptions first and base exception last”.

An important point to note here is that, we need to organize and code our Catch blocks in such a way that more specialized Catch block should come before a generalized one. Otherwise the compiler will show a compilation error.

Also, once the proper Catch code fires off, the control is transferred to the finally block, and then whatever follows the finally block.


Nested Try-Catch

At this point a genuine question might come like, “What happens or What to do when an error occurs while executing the code in the Catch block itself?”

Thinking about this, the obvious solution that comes in mind is to put another Try-Catch block inside the existing Catch block, where the error has or is likely to occur.

This is called nesting of Try-Catch blocks. This ability to nest Try structures has been made available so that we can use a second Try structure to cover the exceptions.


Throwing an Exception

In C#, it is possible to explicitly throw an exception, from the program. The throw keyword is used for doing that. The general form of throwing an exception is as follows.

               System.Exception exception_obj = new ArgumentException("This is my Exception message");
                throw exception_obj;


                                      or

                throw new ArgumentException("This is my Exception message");

Hence, we see that to throw an exception from an operation implementation, you simply instantiate the exception, initialize it, and throw it.  

We could have thrown the exception even without any string/customized message. In this case it would pass on the system defined error message to the catch block.

                 throw new ArgumentException();

However personally speaking, I do not find it a good idea to display the raw exception message to the user. I believe it is better to show a friendly message to the user and log the actual exception message to some log file for troubleshooting purposes.

E.g.--
    try
                          {
                              object m = null;
                              // Creating an exception
                              System.Exception exception_obj = new ArgumentException("My Exception");
                              if (m == null)
                              {
                                  // Throwing the exception
                                  throw exception_obj;
                              }
                              n = m.ToString();
                          }
                          catch (System.Exception ex)
                          {
                              Response.Write("Catch Block ............." + ex.Message + "<BR>");
                          }
                          finally
                          {
                              Response.Write("Finally Block .............");
                          }

Open in new window


Re-throwing an Exception

At times, the business logic/process flow could be such that we may have to re-throw the exception back up the call stack, after the exception has been caught and the associated logic has been executed. This is simply done using the ‘throw’ keyword.

The runtime generates and maintains a stack trace from the point at which an exception is thrown.  If we re-throw the exception, the stack trace is cleared and the originating point of the exception is lost. However, it is possible to re-throw an exception without wrapping it in another exception, i.e. simply using ‘throw’ without specifying an exception.  This re-throws the exception that was currently being handled by the catch block and the original exception propagates up with its stack trace intact.

      catch (Exception ex)
       {
             throw;
       }

E.g.--
    try
                          {
                              try
                              {
                                  Response.Write("Try Block .............. " + "<BR>");
                      
                                  // The original location from where the Exception is being thrown.
                                  throw new DivideByZeroException();                      
                              }
                              catch (Exception ex)
                              {
                                  Response.Write("Inner Catch Block ..............<BR> Message= " + ex.Message + "<BR> Stack Trace = " + ex.StackTrace + "<BR>");
                                  Response.Write("Re-throwing Exception ..............<BR>");
                      
                                  // The Exception is being re-thrown.
                                  throw;
                              }
                              finally
                              {
                                  Response.Write("Inner Finally Block ............." + "<BR><BR><BR>");
                              }
                          }
                      
                          catch (Exception ex)
                          {
                              Response.Write("Outer Catch Block ..............<BR> Message= " + ex.Message + "<BR> Stack Trace = " + ex.StackTrace + "<BR>");
                              }
                      
                          finally
                          {
                                  Response.Write("Outer Finally Block ............." + "<BR><BR><BR>");
                          }

Open in new window


       
Output
Try Block ..............
Inner Catch Block ..............
Message= Attempted to divide by zero.
Stack Trace = at TestApplication._Default.Page_Load(Object sender, EventArgs e) in E:\CQ\ASP .Net\TestApplication\Default.aspx.cs:line 100
Re-throwing Exception ..............
Inner Finally Block .............


Outer Catch Block ..............
Message= Attempted to divide by zero.
Stack Trace = at TestApplication._Default.Page_Load(Object sender, EventArgs e) in E:\CQ\ASP .Net\TestApplication\Default.aspx.cs:line 115
Outer Finally Block .............


“Re-throwing an exception as discussed above is the best and the only correct way of re-throwing an Exception.”

Now that is a very bold statement to make. The obvious question would be - Why?

To understand this, we first need to understand and appreciate the importance of ‘StackTrace’. StackTrace is a read-only property of an Exception, that contains the name of the methods on the current call stack, together with the file name and line number where the exception was thrown for each method. As we could see all this information is quite useful and essential for debugging and pinpointing the location of the exception in the source code. (We would discuss this exception property again in our course of discussion.)

If we use any other form of re-throw, as below, we lose the original StackTrace information. Most important of all, we lose the original line number of the code where the exception was thrown.

      catch (Exception ex)
       {
             throw ex;
       }


The above code might look good, but we are losing the original StackTrace Information. When we examine the stacktrace, we find that the point of the exception is the line of the "throw ex;", rather than the line where the Exception actually originated, thereby hiding the real error location.

Now then, an argument from people could be, “Why don’t we preserve the original Exception Message while initializing a new Instance of the Exception”

      catch (Exception ex)
       {
             throw new Exception(ex.Message,ex);
       }


To this I would say, “A good thought – A good work around”. But is this worth all the effort? I would say stop and think about it –
i)  Is this a re-throw?
Are we not actually throwing an absolutely new exception, as we had discussed above.
ii)  Isn’t just using a ‘throw;’ much simpler, easier and optimized, rather than loading it with attributes and creating a new exception altogether.

I don’t see any point in inventing a workaround, when we already have a simple way to achieve a re-throw in C#.

Note:
1)  A re-throw mechanism might appear useful, having some very potential benefits. However, still I would suggest against using it very often. Do not re-throw an exception for unnecessary reason.  The cost of using throw to re-throw an existing exception is approximately the same as creating a new exception. Also re-throwing an exception also makes it very difficult to debug the code.

2)  I would like to point out one more fact –
What happens after the exception is re-thrown. Does the finally block associated with its catch block get executed or not?

The answer is Yes!  As would be evident from the example that I have given above, though logically it might appear that after executing the ‘throw;’ statement in the inner catch block, the control would be transferred upwards to the outer catch block.  However, on the contrary the fact is that as per the CLR rules, the control goes ahead and executes the corresponding inner finally block, before being transferred upwards to the outer catch block.

Confession:
Before I move ahead into next section of my discussion, I want to own up to one thing. All said and done about Re-Throwing an Exception. If you noticed in the Output of the example that I have given, the stack trace indeed remains the same, but the Line Number of the code which throws the exception changes, no matter whether we use a simple ‘throw;’ or a ‘throw ex;’

I have exhaustively tried to research on this, and everywhere I got the same theory as I have presented above, and this includes the MSDN try-catch documentation as well.  I would urge my readers to check it out. If anyone gets a better understanding or a solution, or any more information, I'd appreciate it if you would post a comment.


Custom Exception Class

The .NET Framework provides a rich set of system-defined exception types. Some of these important and normally-used Exception Types have already been listed above as Standard Exceptions. However, these available exceptions do not cover all the possible exception cases.  At times we might find that it is more appropriate to define custom exceptions for specific error scenarios.

In C#, this could be done by deriving our own new exception class from any of the existing exception types. Any such user-defined exception classes must inherit from either Exception class (usually the ApplicationException class or SystemException class) or one of its standard derived classes.

As we have already said, exceptions in .NET are derived from either of the root exception class –
•  System.SystemException
•  System.ApplicationException

All exceptions thrown by the .NET Framework is derived from the SystemException class. If we raise any exception from our application, it should be derived from the System.ApplicationException. This will differentiate our exceptions from the system-generated exceptions.

Creating a custom exception class is no big deal. We just need to create a new class and derive it from either System.ApplicationException or System.SystemException.

Sample# 1
    public partial class _Default : System.Web.UI.Page
                          {
                               
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  try
                                  {
                                      //Code where exceptions are likely to occur.
                                      Response.Write("Try Block .............. " + "<BR>");
                                      throw new MyException("MyException");
                                  }
                      
                                  catch(MyException ex) 
                                  {
                                              //Code that has to be excuted to handle the Exception
                                              Response.Write("Catch Block .............. " + ex.Msg + "<BR>");
                                  }
                      
                                  finally
                                  {
                                      	   //Code that has to be excuted after the Exception handling.
                                              //This is an optional block.
                                              Response.Write("Finally Block ............." + "<BR>");
                                  }
                               }
                          }
                          
                      
                         //User Defined Exception class, with the user defined code/business logic 
                         //for handling the exception.
                         public class MyException : SystemException
                          {
                              public string Msg;
                              public MyException(string str)
                              {
                                  Msg = "User defined exception from " + str;
                              }
                          }

Open in new window


Sample# 2
public partial class _Default : System.Web.UI.Page
                          {
                               
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  try
                                  {
                                      //Code where exceptions are likely to occur.                
                                      Response.Write("Try Block .............. " + "<BR>");
                                      throw new MyException("I am throwing an exception");
                                  }
                      
                                  catch (MyException ex) 
                                  {
                                      //Code that has to be excuted to handle the Exception
                                      Response.Write("Catch Block .............. " + ex.Message + "<BR>" + ex.Msg);
                                  }
                      
                                  finally
                                  {
                                      //Code that has to be excuted after the Exception handling.
                                      //This is an optional block.                
                                      Response.Write("Finally Block ............." + "<BR>");
                                  }
                               }
                          }
                            
                      
                          //User Defined Exception class, with the user defined code/business logic 
                          //for handling the exception. Note the call to the Base Cunstructor.
                          public class MyException : SystemException
                          {
                              public string Msg;
                              
                              public MyException(string str):base(str)
                              {
                                  Msg = str + "I am inside MyException " + "<BR>";
                              }
                          }

Open in new window


System.Exception Class
All exceptions thrown by the .NET Framework are derived from the SystemException class. If we raise any exception from our application, it should be derived from the System.ApplicationException. This will differentiate our exceptions from the system generated exceptions.

This System.Exception class has a number of useful properties and methods. For example –
Message – It’s a read only property that gives you the error message text that you can display on the screen so that your user can report that back to you.
Source – It’s a read-write property that gets or sets a string containing the name of the application or the object that causes the error.
StackTrace - It’s a read only property that contains the name of the methods on the current call stack, together with the file name and line number where the exception was thrown for each method. A StackTrace object is created automatically by the common language runtime (CLR) from the point of the throw statement, so that exceptions must be thrown from the point where the stack trace should begin.
InnerException - It’s a read only property that returns the same value as was passed into the constructor, or a null reference if the inner exception value was not supplied to the constructor.
HelpLink - It’s a read-write property that Gets or sets a link to the help file associated with this exception.
TargetSite - It’s a read only property that obtains the method from the stack trace, if the method that throws this exception is not available and the stack trace is not a null reference.

The Exception class has three methods of its own. They are:
GetBaseException. This method returns the original, innermost exception that causes this exception and other related exceptions, linked via the InnerException property. If the current exception is the only one thrown, then its reference will be returned.
GetObjectData. This method sets SerializationInfo with the entire exception object data targeted for serialization. During deserialization, the exception object is reconstituted from the SerializationInfo transmitted over the stream.
ToString. This method returns the fully qualified name of this exception, and possibly the error message, the name of the inner exception, and some other information.


Page Level and Application Level Error Event Handlers

This is very useful in cases where an exception is unexpected and does not occur within the bounds of a try-catch-finally block. These exceptions are usually an indicator that something is substantially wrong with the application. That is, some abnormal exception has occurred and no means are provided to handle exception. In this case there is the option to deal with the error at either the Page or Application level.

There are three different error events in ASP.NET that can be used in conjunction with Structured  Error Handling (try-catch-finally block), so that all exceptions are handled and the user is presented with a user-friendly error message.

1.  OnError
By default The .NET Framework will call the Page's OnError( ) method when an unhandled exception occurs.
2.  Page_Error
This event occurs when an error occurs within the Web page. This event is in the Web form.
3.  Application_Error
This event occurs when an error occurs within the application. This event is in the Gloabl.asax file.

These events are raised whenever an unhandled exception occurs within an application. If a Page_Error event is present within an ASP.NET page, and an unhandled error occurs, the event is raised. Application_Error is slightly different. It is raised for all unhandled exceptions in the ASP.NET application and is implemented in global.asax or within an HTTP Module.

Useful methods of the Server Object
There are two methods in the Server object, which could be used to handle the exception in the error events.
1.  GetLastError
Gets the last exception that occurred on the server.
2.  ClearError
Use this method to handle the exception and prevent the error from triggering the subsequent error event or displaying the error to the user.  If we do not call Server.ClearError()in either of OnError, or Page_Error or Application_Error, then the exception will leave the method/event and continue to crawl up the stack until it has been handled and put to rest.

AutoEventWireup
Before we move on and discuss these Events and method in detail, it is important to note that it is essential/mandatory to keep the AutoEventWireup="true", in the .aspx file.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestApplication._Default" %>

By keeping the AutoEventWireup="true" the page framework will call all of the page events automatically. An explicit handles clause or delegate for these events would not be needed.


Trapping Errors On Page Level

The first level of error handling happens at the page level. The two events that can be used to catch the error are –
1.  OnError()
2.  Page_Error()

1.  OnError()
With the permission of you all, I am calling OnError() an event, just for the sake of discussion. Else it is actually a virtual method in the TemplateControl class available in the System.Web.UI namesapace. When this method is called, it raises the System.Web.UI.TemplateControl.Error event.

Whenever an Error occurs and an unhandled exception is thrown, the .NET Framework, by default calls the Page's OnError( ) method. Now, as this method is protected and virtual, hence we are free to override it in our page, in order to handle the error as per our requirement and/or design.

This code is implemented in the .aspx file
    public partial class _Default : System.Web.UI.Page
                          {
                               
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  throw new SystemException("This is an unhandled exception.");
                              }
                      
                              protected override void OnError(EventArgs e)
                              {
                                  HttpContext ctx = HttpContext.Current;
                                  Exception ex = ctx.Server.GetLastError();
                                  Response.Write("Executing OnError: " + ex.Message + "<BR>");
                                  base.OnError(e);
                                  Server.ClearError();
                              }
                          }

Open in new window


I think we should note and appreciate the fact that, as the .Net framework automatically calls OnError() at the appropriate time, and as this method is protected and virtual making it possible for us to override it, then I don’t think that we actually need to make the effort of hooking up any event handler to archive the objective of Error Handling. Also, this fact makes it much optimized way of Error Handling. But then again, the logic and design is all yours to decide what you want do.

Important Note:
Before we close the discussion on this method, there is one more important think to be noted. We must remember to call the base.OnError( ). Calling this method from the base class hooks up all the other existing event handlers, otherwise they won't be fired.

Please remember, the OnError fires first. Hence if we have the implementation of both the OnError() and the Page_Error(), and if the base.Error() is not called, then the Page_Error() will not be executed.

2.  Page_Error()
Almost similar to OnError() the Page_Error() Event could also be used to trap page-level errors.

This code is implemented in the .aspx file
    public partial class _Default : System.Web.UI.Page
                          {
                               
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  throw new SystemException("This is an unhandled exception.");
                              }
                      
                              private void Page_Error(object sender, EventArgs e)
                              {
                                  Exception Ex = Server.GetLastError();
                                  Response.Write(“Page_Error:- ” + Ex.Message);
                                  Server.ClearError();
                              }
                          }

Open in new window


In my discussions, I have often come across the arguments that handling Errors through OnError() event is the same as doing it through the Page_Error() event. However, my argument is; “It Is Not”.

As per the MSDN, the difference lies in the fact that whenever the OnError() is raised, it in turn hands over the control to the private HandleError() method. At this point the .NET framework checks for two things –
(i)  Whether customErrors is turned on.  If yes, then it redirects the control when an exception is raised.
(ii)  Whether tracing is turned on.  If yes, then it adds its own bit about the exception just raised.

Moreover, the main reason to override OnError is to replace this behavior with our own functionality or business logic. There is no good reason to put other code there.

Important Note:
I am reiterating, please remember, the OnError fires first. Hence if we have the implementation of both the OnError() and the Page_Error(), and the base.Error() is not called then the Page_Error() will not be executed.


Trapping Errors On Application Level : Application_Error

The Application_Error event handler could be used to trap errors that occur at the application level. The implementation is the same as in Page_Error().

This event is implemented in the global.asax file. When an error occurs, first the Page_Error is called, and then the Application_Error. Due to the event's application-wide scope, here we can either log the application error information or redirect to another page or handle the error, as per the requirement or business logic.

Let’s try and look at it, with a little more insight.

Whenever we request a page in our browser, our request travels through the ASP.NET pipeline. IIS treats each virtual directory as an application. Hence, when a request within a certain virtual directory is placed, an instance of HttpApplication is created, to process the request. The runtime maintains a pool of HttpApplication objects. The same instance of HttpApplication services the request it is responsible for. This instance can be pooled and reused only after it is done processing a request.

Now, as I said earlier, Global.asax is optional. Hence, if we do not want to use any session or application events we could very well live without it. Otherwise the ASP.NET runtime parses our global.asax, compiles a class derived from HttpApplication and hands it a request for our web application. Now finally the HttpApplication fires a number of events, which includes the Error event as well.

Here we need to note that, if we are using the session or application events, and modifying the Global.asax file, then we would need to be a little careful. The .NET framework detects that we have changed the Global.asax. It then flushes all session state and closes all browser sessions. When a new page request arrives, the framework parses the Global.asax file and compiles a new object derived from HttpApplication again.

This code is implemented in the .aspx.cs file
    public partial class _Default : System.Web.UI.Page
                          {
                               
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  throw new SystemException("This is an unhandled exception.");
                              }
                      
                          }

Open in new window

This code is implemented in the Global.asax.cs file
    public class Global : System.Web.HttpApplication
                          {
                              protected void Application_Error(object sender, EventArgs e)
                              {
                                  Exception Ex = Server.GetLastError();
                                  Response.Write("Application_Error:- " + Ex.Message);
                                  Server.ClearError();
                              }
                          }

Open in new window

You must have noticed that, the Page_Error and Application_Error are quite similar, as --
1.  They take the same arguments, and
2.  They can even contain the same code.

However, their difference lies in the fact that, the Page_Error is built inside the .aspx file (or its code-behind), while the Application_Error is built inside global.asax (or an IHttpHandler class assembly).

Note:  I would like to point out one more thing:  The only two locations that actually give us access to Server.GetLastError are in the Page_Error and Application_Error.


Global_Error

While reading about Exceptions and Exception Handling, we often get references to Global_Error event.

However, there is not much official documentation available on this event.

The only information that is available for this event says that, this event is in the Gloabl.asax file. It is called whenever an error occurs while compiling or running the Global.asax file. Anything more than this is still in a haze.

At least, in my case I have no more information on this event. If anybody has any information, please feel free to share it with me. I would greatly appreciate it.


Custom Errors

The Custom Error is the last method to handle errors. If we have other error handlers in place, like the Application_Error, Page_Error or OnError, then these would be called first and the Custom Error Page the last.

Let’s try and analyze the utility of Custom Error Pages, with a ‘problem – solution’ point of view -

Problem #1
When exceptions are left unhandled, the ASP.NET by default, displays a page with an exception stack trace which reveals a part of the code and how it works. This information, if it gets into the hands of a hacker, may have serious security consequences.
Solution
Custom error Pages. This would give the user a more friendly and useful , but at the same time a secure set of information.

Problem #2
When exceptions are left unhandled, the ASP.NET by default, displays a page with an exception stack trace which reveals a part of the code and how it works. This information, if it gets into the hands of a hacker, may have serious security consequences.
Solution
Custom Error Pages. If we set custom error pages in web.config. the runtime will act accordingly— the user would get a more friendly and useful , but at the same time a secure set of information.

Problem #3
If we request a nonexistent page (either html or aspx), and if the Exceptions are left unhandled, the ASP.NET by default, displays a white page with a message; “The resource cannot be found.”.
Solution
Custom Error Pages. If we set custom error pages in web.config. the runtime will act accordingly—the user would get a more friendly and useful , but at the same time a secure set of information.

Hence we see that the Custom Error Pages are not a luxury, instead they are a must-have.

The ASP .Net also has a built in detailed error page, which is by default displayed to the user in the event of an exception. However template of this error page is fixed, it simply contains the Description of the error, the Exception Details, the code and the stack trace etc. These details at times may be useful, though they are not all that would be needed to handle an exception or for debugging etc.

I personally feel, that an error page should be useful for both the developers and the end-users. It should give a user-friendly and good look and feel of the site, at the same time it should provide enough information to the developers to identify and debug the error. However it should also hide the data that is irrelevant or anything that might pose a security threat.

Now as the default error page as provided by ASP .Net cannot be customized, thus we are left with no other option, than to develop our own (customised) Error Page.

Custom Errors Pages can be setup at 2 levels –
i.  Application Level
ii.  Page level

Page Level – Custom Errors

At the Page Level, the Custom Error Page can be setup as an errorPage attribute of the @Page directive of the Web form. This directive specifies where the error page is to be redirected if an error occurs in the Web page.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestApplication._Default" errorPage="Error.aspx" %>


Application Level – Custom Errors

At the application Level, the redirection to a custom error-page can be setup in web.config. We have a customErrors tag in the web.config file. If an exception has not been handled by the Page object, or the HttpApplication object and has not been cleared through Server.ClearError() it is taken care as per the ‘customErrors’ settings in the  web.config. Due to the global i.e. application level scope of these settings in web.config, it is often called Global Exception Handling.

< customErrors mode="On" defaultRedirect="error.aspx" />

The attributes of the < customErrors > tag are:

i)  mode: this attribute has three possible values:

On: This attribute value specifies that the custom errors are enabled. The specified custom error page will always be shown, both to the remote clients as well as to the local host. However, if an error page is not specified or the ‘defaultRedirect’ attribute is not present, then the users would by default get the generic error page being served by the ASP .Net.

Off: This attribute value specifies that custom errors are disabled. At all times, the default ASP .NET errors page is shown to both the remote clients and to the local host. Although a custom error page might also be specified in the ‘defaultRedirect’ attribute.

RemoteOnly This is the default value.  This attribute value specifies that custom errors are shown only to the remote clients, the local host get the default ASP.NET errors page.

ii)  defaultRedirect: This attribute specifies the name of the custom error page (along with the path, if required), that has to be delivered in the event of an exception.

Hence, we see that if an unhandled exception occurs, the user will be redirected to the specified Custom Error Page. However, what if this custom error page does not exist or is inaccessible? Do we have the capability to take care of such scenarios where the specified custom error page is not available or to specifically handle different known errors.

Yes!  We have the option to setup specific Custom Error pages for Specific known errors depending upon their HTTP status code. For example, a custom error page if the request attempts to access a page does not exist (HTTP 404).

The <customErrors> tag contains <error> subtags for handling such scenarios of specific known errors. Each <error> tag allows us to set a specific Custom Error page, which should be rendered in case of that particular error, based upon its HTTP status code. Also, we could specify several such <error> subtags in a single <customErrors> tag.

      <customErrors mode="On" defaultRedirect="error.aspx" >
                              	<error statusCode="403" redirect="error403.aspx" />
                       	<error statusCode="404" redirect="error404.aspx" />
                       	<error statusCode="500" redirect="error500.aspx" />
                            </customErrors>

Open in new window


Sample#
1.  This code is implemented in the web.config file

<?xml version="1.0"?>
                      <configuration>
                      
                          <system.web>
                      
                              <compilation debug="true" targetFramework="4.0" />
                      
                            	 <customErrors mode="On" defaultRedirect="error.aspx" >
                              	<error statusCode="403" redirect="error403.aspx" />
                       	<error statusCode="404" redirect="error404.aspx" />
                       	<error statusCode="500" redirect="error500.aspx" />
                            	 </customErrors>
                      
                          </system.web>
                      
                      </configuration>

Open in new window



2.  This code is implemented in the web.config file

    public partial class _Default : System.Web.UI.Page
                          {
                               
                              protected void Page_Load(object sender, EventArgs e)
                              {
                                  
                                  throw new SystemException("This is an unhandled exception.");
                                  
                               }
                          }

Open in new window


3.  Design and implement the Custom Error Pages as per your requirement/business logic.

Note: Now that we know all the different levels and methods of handling exceptions, we should note that in case if someone gets over enthusiastic and tries to use all levels of exception handling all at once, then the following precedence is followed by the framework in handling the exceptions:

1.  Try-catch-finally block (Structured Exception Handling) only.
2.  Page Level – Custom Error only.
3.  onError() and then Application_Error().
4.  Page_Error only.
5.  Application_Error() only.
6.  Application Level – Custom Error as specified in Web.config.


Best Practices for Exception Handling

Exception Handling is an important and an indispensable part of our application design and implementation. The .NET framework itself provides a rich set of standard exceptions that are used during exceptions handling. However Exception Handling is an expensive process, we should use exceptions wisely; let’s say only in exceptional situations and not to control the regular logic flow.

I have consolidated the following list of industry best practices for Exception Handling. Though, the choice of the scenarios and the methodology, for exception handling is purely the discretion of the Designer and the Developer. It would vary from case to case basis.

1

Wherever possible, always implement a single try with multiple catches. Enclosing the code where an exception is expected in a single try and then catching all the anticipated exceptions in the consecutive multiple catches increases the readability of the code.

2


When implementing multiple catches, try to order all catch blocks from specific to general. This would make sure the specific exception types will be handled before the more general types. It will also increase the readability of the code.

3


Do not catch and re-throw exceptions unless you are adding additional information or changing the type of the exception, because cost of using throw to re-throw an existing exception is approximately the same as creating a new exception and re-throw exception also makes very difficult to debug the code.

4


Avoid exception handling inside loops, if it’s really necessary implement try/catch block surrounding the loop.

5


Take care in what information you provide in the exception message, i.e. might pose security threat.  For instance, avoid using the IP address of the Server, or the file/directory path, or an SQL Query etc. Any such information might prove fatal in the hands of a hacker.

6


Always Throw an exception instead of returning an error code or HRESULT.

7


Wherever possible, use validation code to avoid unnecessary exceptions, i.e. try to use available methods to avoid exceptions. Instead of using Exception Handling. E.g. - File.Exists() method could be used to avoid a FileNotFoundException.

8


Try to use Standard Exception Classes in most cases.  A new Custom Exception Class should only be defined if a specific action has to be taken or a business logic needs to be implemented, based on a specific type of Exception. Too many Custom Exception Classes tend to have negative impact on performance and maintenance.

E.g. – In the event of non-availability of a file, a FileIOException is raised. If we want to specifically implement something other than the normal behavior of this Standard Exception Class, then we could create our own Custom Exception Class.

9


Do not derive all new exceptions directly from the base class SystemException. Inherit from SystemException only when creating new exceptions in System namespaces. Inherit from ApplicationException when creating new exceptions in other namespaces.

10


Implement all the Custom Exception Classes with similar built-in logic or related to some common exception criteria under a common namespace. For example, all of your custom exception classes that relate to file handling could be grouped together in one namespace and the other set of custom exception classes related to database handling or ADO could be grouped together in a separate namespace.  Emulate the way .Net itself does that: In .Net, all the classes related to reading and writing to files and data streams (e.g. IOException, class, PipeException class etc.) are grouped under System.IO namespace.
That list could be a lot longer, but that would go beyond the scope of what this article has discussed.  If anybody is interested in exploring this topic further, I would recommend the following articles, which I find quite productive --

1.  Best Practices for Handling Exceptions
     – Article in MSDN Library
     http://msdn.microsoft.com/en-us/library/seyhszts(VS.71).aspx

2.  Best Practices for C# Exception Handling
     http://www.anticipatingminds.com/content/products/devadvantage/KnowledgePacks/ErrorHandling/ErrorHandlingKPOverview.aspx

3.  Exception Handling Best Practices in .NET
     - by Daniel Turini
     http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx


Conclusion

In this article so far, we discussed that Exceptions are unusual error conditions that occur during execution of a program or an application. We also to rationalize the need of Exception Handling and agreed that handling exceptions properly is one of the key factors for the success of the any Application. We discussed the various methods available in .Net to handle the Exceptions. Finally we shared some of the as best practices for Exception Handling.

The various methods of Exception Handling that we discussed here are namely –
  1.  Try-catch-finally block (Structured Exception Handling) only.
  2.  Page Level – Custom Error only.
  3.  onError() and then Application_Error().
  4.  Page_Error only.
  5.  Application_Error() only.
  6.  Application Level – Custom Error as specified in Web.config.

All these methods are the very basic and fundamental building blocks of Exception Handling in .Net. There is much more to this discussion. We have some more advance and very effective methods and strategies of Exception Handling available in .Net. that will be covered in a future article.

Please, let me know your feedbacks. Good or Bad, I would appreciate.


References

Some very good articles that helped me in presenting my thoughts to you and added value to my article.

1.  Design Guidelines for Exceptions - .NET Framework 3.0
     -  MSDN Article
     -  http://msdn.microsoft.com/en-us/library/ms229014(v=VS.85).aspx

2.  Exceptions and Exception Handling (C# Programming Guide)
     -  MSDN Article
     -  http://msdn.microsoft.com/en-us/library/ms173160.aspx

3.  Exception Class
     -  MSDN Article
     -  http://msdn.microsoft.com/en-us/library/system.exception.aspx

4.  System.Exception Class
     -  http://www.gnu.org/projects/dotgnu/pnetlib-doc/System/Exception.html

5.  Learning the C# Error Handling Mechanism
     -  by Budi Kurniawan
     -  http://ondotnet.com/pub/a/dotnet/2001/09/04/error_handling.html
3
8,189 Views
Ritesh RatnaBusiness Analyst/SharePoint Consultant

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.