Exception/Error Handling in ASP.Net Simplified

Introduction

Guys, this is not first time when something is written for exceptions and error handling in the web. There are enormous articles written earlier for this topic. I have tried writing this article for beginners explaining these concepts in simple language and step-by-step.

This is a very basic article for beginners that show exception handling and error handling techniques in ASP.NET.

Where there are codes, the chances for exceptions / error always exist so it is very important for developers when developing web applications to understand the errors and implement the error handling techniques to avoid breaking pages or providinig unhandled errors to end uses.

What Exceptions are

Guys, the MSDN says that an exception is an error condition or unexpected behavior encountered by an executing program. Exceptions can be raised because of a fault in your code or in code that you call (such as a shared library), unavailable operating system resources or unexpected conditions the Common Language Runtime encounters (such as code that cannot be verified).

Exceptions are nothing but unseen error occurs when executing code logic.

Demo Web Application

I have created a web application as an example to understand the exception handling.

Sample Code

  1. namespace ErrorHandlingDemo  
  2. {  
  3.     public partial class _Default : Page  
  4.     {  
  5.         protected void Page_Load(object sender, EventArgs e)  
  6.         {  
  7.             if (!IsPostBack)  
  8.             {  
  9.                 string connectionString = ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString;  
  10.                 string selectSQL = "SELECT * FROM tblEmployees";  
  11.                 SqlConnection con = new SqlConnection(connectionString);  
  12.                 SqlCommand cmd = new SqlCommand(selectSQL, con);  
  13.                 SqlDataAdapter adapter = new SqlDataAdapter(cmd);  
  14.                 DataSet ds = new DataSet();  
  15.                 adapter.Fill(ds, "Employees");  
  16.                 GridView1.DataSource = ds;  
  17.                 GridView1.DataBind();  
  18.             }  
  19.         }   
  20.     }  
  21. }  
Using this web page I am trying to display employee's details in a grid view control on page load. The following is the output page with employee details. 

MVC 4 Page

Example to show data on the webpage from the database using some ADO.NET code:

Now from this basic what if the table containing employees is deleted or renamed or the developer has used the wrong table name in the code behind.

I have now changed the table name in the code and complied and run the page.

  1. string selectSQL = "SELECT * FROM tblEmployees1";  
After running the application a broken Yellow screen is shown with the message Invalid Object name. 

Server Error

But exposing this error message in Yellow page format is a bad practice because:

  • It does not make any sense to the end user although it can be helpful for developers for debugging and investigating the issue.
     
  • This exposure can help hackers to get information about your application that is not good according to security.

Handling Exceptions

Using Try catch finally Block

Using a try catch finally block, exceptions can be handled.

Whenever an exception happens when executing the logic in a try block, the control is immediately moved to the catch block that reads the exception message and after catching the exception in the catch block a user-friendly error can be shown to the end users.

Sample Code

  1. namespace ErrorHandlingDemo  
  2. {  
  3.     public partial class _Default : Page  
  4.     {  
  5.         protected void Page_Load(object sender, EventArgs e)  
  6.         {  
  7.             if (!IsPostBack)  
  8.             {  
  9.                 try  
  10.                 {  
  11.                     string connectionString = ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString;  
  12.                     string selectSQL = "SELECT * FROM tblEmployees1";  
  13.                     SqlConnection con = new SqlConnection(connectionString);  
  14.                     SqlCommand cmd = new SqlCommand(selectSQL, con);  
  15.                     SqlDataAdapter adapter = new SqlDataAdapter(cmd);  
  16.                     DataSet ds = new DataSet();  
  17.                     adapter.Fill(ds, "Employees");                  
  18.                     GridView1.DataSource = ds;  
  19.                     GridView1.DataBind();  
  20.                 }  
  21.                 catch (Exception ex)  
  22.                 {  
  23.                     // Log the exception                      
  24.                     Label1.Text = "Something Bad happened, Please contact Administrator!!!!";  
  25.                 }  
  26.                 finally  
  27.                 {  
  28.                 }  
  29.             }  
  30.         }  
  31.     }  
  32. }  
Running View Page

Apart from the try catch exception handling technique, the ASP.NET Framework has error handling events where exceptions can be caught.

When there is an unhandled error at the code level, meaning if the code does not have a structured try catch block to handle exceptions, then that can be handled at the page level. 

An unhandled exception is being propagated to the page level if not handled at the code level.

At the page level Page_Error is the event that catches the exception and we can handle the exception at the page level.

If an exception is not handled at the page level then it will be propagated to the application level and at the application level in the global.aspx file there is an application_Error event where the exception can be handled.

It could be a centralized place to handle all the required exception handling at the project level.

  • Page level error event
    1. protected void Page_Error(object sender, EventArgs e)  
    2. {  
    3.     Exception Ex = Server.GetLastError();  
    4.     Server.ClearError();  
    5.     Response.Redirect("Error.aspx");  
    6. }  
    Error Calling View Page
     
  • Application level error event
    1. void Application_Error(object sender, EventArgs e)  
    2. {  
    3.      // Code that runs when an unhandled error occurs  
    4.     Exception Ex =Server.GetLastError();  
    5.     Server.ClearError();  
    6.     Server.Transfer("Error.aspx");  
    7. }  

Exception Propagation at ASP.NET web application

Exception Propogation

Custom Error in ASP.NET

An exception in the application can be handled using the custom error pages.

Custom error pages can be displayed instead of a Yellow broken page as per the exception if it is not handled at any lower level.

Custom error pages are displayed depending on the ASP.NET HTTP status codes.

It can be defined at two levels.

  1. Application level: In the web.Config File

    In the Webconfig file at the application root level we need to set the CustomErrors element “On” and error with statusCode and Redirect.
    1. <customErrors mode="On" defaultRedirect="DefaultError.aspx">  
    2.     <error statusCode="404" redirect="PageNotFound.aspx"/>  
    3.     <error statusCode="500" redirect="ServerError.aspx"/>   
    4. </customErrors>  
    Server Error Page

    A Custom Errors Element has the following three modes available:
     
    1. Off: Custom Error pages are not displayed.
       
    2.  On: Custom Error page are displayed on both local and remote machines
       
    3. Remote Only: Custom Error pages are displayed on the remote machine and an exception on
      the local machine
       
  2. Page Level: At Page directive

    We can set the custome error page at the page level using as below:
    1. ErrorPage="~/ServerError.aspx"  
    Page Directive

It will work especially for this page only.

Note

If Pagelevel custom error, the application level custom error and redirection from application_error from global.aspx are present then the page level has the highest priority then application_error and then application level custom in web Config file.

Exception Logging In ASP.NET

  • Logging to Event Viewer
  • Logging to Database Table
  • Logging to Text file

Logging to Event Viewer

The Wiki says, the Event Viewer is nothing but an Event Viewer, a component of Microsoft's Windows NT line of operating systems. It lets administrators and users view the event logs on a local or remote machine.

Go to Run -> Type EentVwr.

Event Viewer

Event Log Types

  1.  Application Log
     
  2.  Security Log
     
  3. System Log

In the Application and Service Logs, I have created a Custom Event Log with the following details using the code.

  1. EventLog.CreateEventSource("AbhiTesting""TestLog");  
Log Name: Test Log
Source: AbhiTesting

You can modify the Name and source depending on your requirements and provide some dynamic way to create it I have hardcoded the values.

Event Viewer TestLog

Exception

Sample Code

  1. public static void LogErrorToEventViewer(Exception ex)  
  2. {  
  3.     StringBuilder sb = new StringBuilder();  
  4.     sb.Append("********************" + " Error Log - " + DateTime.Now + "*********************");  
  5.     sb.Append(Environment.NewLine);  
  6.     sb.Append(Environment.NewLine);  
  7.     sb.Append("Exception Type : " + ex.GetType().Name);  
  8.     sb.Append(Environment.NewLine);  
  9.     sb.Append("Error Message : " + ex.Message);  
  10.     sb.Append(Environment.NewLine);  
  11.     sb.Append("Error Source : " + ex.Source);  
  12.     sb.Append(Environment.NewLine);  
  13.     if (ex.StackTrace != null)  
  14.     {  
  15.         sb.Append("Error Trace : " + ex.StackTrace);  
  16.     }  
  17.     Exception innerEx = ex.InnerException;  
  18.     while (innerEx != null)  
  19.     {  
  20.         sb.Append(Environment.NewLine);  
  21.         sb.Append(Environment.NewLine);  
  22.         sb.Append("Exception Type : " + innerEx.GetType().Name);  
  23.         sb.Append(Environment.NewLine);  
  24.         sb.Append("Error Message : " + innerEx.Message);  
  25.         sb.Append(Environment.NewLine);  
  26.         sb.Append("Error Source : " + innerEx.Source);  
  27.         sb.Append(Environment.NewLine);  
  28.         if (ex.StackTrace != null)  
  29.         {  
  30.         sb.Append("Error Trace : " + innerEx.StackTrace);  
  31.         }  
  32.         innerEx = innerEx.InnerException;  
  33.     }  
  34.     if(EventLog.SourceExists("AbhiTesting"))  
  35.     {  
  36.         EventLog eventlog=new EventLog("TestLog");  
  37.         eventlog.Source = "AbhiTesting";  
  38.         eventlog.WriteEntry(sb.ToString(), EventLogEntryType.Error);  
  39.     }  
  40. }  

 Error Check


EventLogentry has options to write the error as various entry types.

Creating Custom View

Event Properties

The Windows Event Log can be used to store the error logs for developers to see the error messages and provide solutions to the issues.

Logging to Database Table

An exception can be written to a database table for the developer to get the log and investigate the error to provide a solution for it.

Table Script

  1. CREATE TABLE [dbo].[tblExceptionLog]  
  2. (  
  3.     [ID] [int] IDENTITY(1,1) NOT NULL,  
  4.     [ExceptionMesage] [nvarchar](max) NULL,  
  5.     [LogDate] [datetime] NULL,  
  6.     [Source] [varchar](50) NULL,  
  7.     [Trace] [varchar](max) NULL,  
  8.     CONSTRAINT [PK_tblExceptionLog] PRIMARY KEY CLUSTERED   
  9.     (  
  10.     [ID] ASC  
  11.     )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS =      ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
  12. ) ON [PRIMARY]  
Stored Procedure
  1. Create PROCEDURE Sp_LogException  
  2. (  
  3.     @ExceptionMessage nvarchar(max),  
  4.     @Source Varchar(50)  
  5. )  
  6.   
  7. AS  
  8. BEGIN  
  9.         SET NOCOUNT ON;  
  10.     INSERT INTO [School].[dbo].[tblExceptionLog]  
  11.     ([ExceptionMesage]  
  12.     ,[LogDate]  
  13.     ,[Source]  
  14.     ,[Trace])  
  15.     VALUES  
  16.     (@ExceptionMessage,GETDATE(),@Source,null)  
  17. END  
Sample Code
  1. public static void LogErrorToDB(Exception ex)  
  2. {  
  3.     StringBuilder sb = new StringBuilder();  
  4.     sb.Append("********************" + " Error Log - " + DateTime.Now + "*********************");  
  5.     sb.Append(Environment.NewLine);  
  6.     sb.Append(Environment.NewLine);  
  7.     sb.Append("Exception Type : " + ex.GetType().Name);  
  8.     sb.Append(Environment.NewLine);  
  9.     sb.Append("Error Message : " + ex.Message);  
  10.     sb.Append(Environment.NewLine);  
  11.     sb.Append("Error Source : " + ex.Source);  
  12.     sb.Append(Environment.NewLine);  
  13.     if (ex.StackTrace != null)  
  14.     {  
  15.         sb.Append("Error Trace : " + ex.StackTrace);  
  16.     }  
  17.     Exception innerEx = ex.InnerException;  
  18.     while (innerEx != null)  
  19.     {  
  20.         sb.Append(Environment.NewLine);  
  21.         sb.Append(Environment.NewLine);  
  22.         sb.Append("Exception Type : " + innerEx.GetType().Name);  
  23.         sb.Append(Environment.NewLine);  
  24.         sb.Append("Error Message : " + innerEx.Message);  
  25.         sb.Append(Environment.NewLine);  
  26.         sb.Append("Error Source : " + innerEx.Source);  
  27.         sb.Append(Environment.NewLine);  
  28.         if (ex.StackTrace != null)  
  29.         {  
  30.             sb.Append("Error Trace : " + innerEx.StackTrace);  
  31.         }  
  32.         innerEx = innerEx.InnerException;  
  33.     }  
  34.     String Connection = ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString;  
  35.     SqlConnection conn = new SqlConnection(Connection);  
  36.     SqlCommand cmd = new SqlCommand("Sp_LogException", conn);  
  37.     cmd.CommandType = CommandType.StoredProcedure;  
  38.     SqlParameter param = new SqlParameter();  
  39.     cmd.Parameters.Add("@ExceptionMessage", SqlDbType.NVarChar).Value = sb.ToString();  
  40.     cmd.Parameters.Add("@Source", SqlDbType.VarChar).Value ="Your Appliaction Name";  
  41.     conn.Open();  
  42.     cmd.ExecuteNonQuery();  
  43.     conn.Close();  
  44. }  
Global.aspx Error Event
  1. Application_Error(object sender, EventArgs e)  
  2. {  
  3.     // Code that runs when an unhandled error occurs  
  4.     Exception Ex = Server.GetLastError();  
  5.     Server.ClearError();  
  6.     // ExceptionLogging.LogErrorToEventViewer(Ex);  
  7.     ExceptionLogging.LogErrorToDB(Ex);  
  8.     Server.Transfer("Error.aspx");  
  9. }  
Data Stored in DB 

SQL View

Logging to Text file

An exception can be logged to a text file also according to the application requirements and company policy. I have provided the example to a written log to a text file at root directory of the application. You can modify the code and store to a server or to a folder for the error log for debugging and investigating the issues.

Sample Code:

  1. public static void LogErrorToText(Exception ex)  
  2. {  
  3.     StringBuilder sb = new StringBuilder();  
  4.     sb.Append("********************" + " Error Log - " + DateTime.Now + "*********************");  
  5.     sb.Append(Environment.NewLine);  
  6.     sb.Append(Environment.NewLine);  
  7.     sb.Append("Exception Type : " + ex.GetType().Name);  
  8.     sb.Append(Environment.NewLine);  
  9.     sb.Append("Error Message : " + ex.Message);  
  10.     sb.Append(Environment.NewLine);  
  11.     sb.Append("Error Source : " + ex.Source);  
  12.     sb.Append(Environment.NewLine);  
  13.     if (ex.StackTrace != null)  
  14.     {  
  15.         sb.Append("Error Trace : " + ex.StackTrace);  
  16.     }  
  17.     Exception innerEx = ex.InnerException;  
  18.   
  19.     while (innerEx != null)  
  20.     {  
  21.        sb.Append(Environment.NewLine);  
  22.         sb.Append(Environment.NewLine);  
  23.         sb.Append("Exception Type : " + innerEx.GetType().Name);  
  24.         sb.Append(Environment.NewLine);  
  25.         sb.Append("Error Message : " + innerEx.Message);  
  26.         sb.Append(Environment.NewLine);  
  27.         sb.Append("Error Source : " + innerEx.Source);  
  28.         sb.Append(Environment.NewLine);  
  29.         if (ex.StackTrace != null)  
  30.         {  
  31.             sb.Append("Error Trace : " + innerEx.StackTrace);  
  32.         }  
  33.         innerEx = innerEx.InnerException;  
  34.     }  
  35.     string filePath = HttpContext.Current.Server.MapPath("ErrorLog.txt");  
  36.     if (File.Exists(filePath))  
  37.     {  
  38.         StreamWriter writer = new StreamWriter(filePath, true);  
  39.         writer.WriteLine(sb.ToString());  
  40.         writer.Flush();  
  41.         writer.Close();  
  42.     }  
  43. }  
Conclusion

Guys we have seen in the preceding about the exceptions happening at the application level and various levels and determine how and where to handle and log the errors.

Exceptions/Errors in an ASP.NET web application propagates from code to the page to the application level.

You can handle and use the error handling techniques according to  the project and company policy. It is very important to understand the requirements and uses of available techniques for the better performance and error handing.

Keep Smiling.

MSDN References

http://www.asp.net/web-forms/tutorials/aspnet-45/getting-started-with-aspnet-45-web-forms/aspnet-error-handling

http://support2.microsoft.com/kb/308427