Click here to Skip to main content
15,881,139 members
Articles / Web Development / HTML

Exception Handling and .NET

Rate me:
Please Sign up or sign in to vote.
4.30/5 (28 votes)
29 Aug 2013CPOL5 min read 100.3K   768   70   39
Exception Handling and .NET - a practical approach

Before We Start

Before you start reading this article you need to ensure you satisfy all the pre-requisites. You must:

  • be familiar with .NET Framework 2.0 or above
  • have C# coding skills
  • have knowledge of SQL Server 2005 or above
  • be familiar with Visual Studio 2005 or above
  • be familiar with creating web application in Visual Studio 2005 or above

Overview

Error Handling has always been crucial for an application in a number of ways. It may affect the execution state of the application, or expose sensitive information to a user. If the error handling is not strong, it may aid the attacker, as the errors returned may assist them in constructing correct attack factors.

An important part of secure application development is to prevent leakage of superfluous information to end user. Error messages (if not proper) may give an attacker great insight into the inner workings of an application.

Exception Handling and .NET

Right Approach

This content focusses more on technical feasibility and implementation of the same, we see here how the points discussed above are disguised in the form of code and learn how to implement these points practically in our application.

Consider the Following Live Scenarios

Let's have an aspx page with the following controls, a textbox, a button and a gridview,

When user inputs a student id in the textbox and submits the form by clicking submit button(Populate Grid), the gridview gets populated with the details of the student as per student id.

Image 1

Code to populate grid

aspx:

Image 2

.cs :

Image 3

Following are the points that need to be taken care of,

  1. The text box value must be an integer value. (Input Validation)
  2. The student id provided should be greater than 0 and less than 5. (Business Logic Validation)

These are the rules known to a developer, but what if end user uses the application? Let's sneak peek into such scenario:

Scenario 1 : User inputs correct value and presses submit button.

Image 4

Here we get the desired result

Scenario 2: User inputs a string or junk character and presses submit button,

Image 5

Results in:

Image 6

As we can clearly see, whole of the code is exposed to end user which is ethically meaningless.

Instead one should display a meaningfull message to the user, so that next time he inputs correct info.

Therefore we need to wrap our code with a try, catch block.

Image 7

and following piece of code in aspx page:

<div>
    <asp:Label runat="server" ID="lblErrorDisplay" ForeColor="Red" FontBold="true" Visible="false" Font-Size="Medium" ></asp:Label>
</div>

Now when user inputs value other than integer, he is shown a meaningful message as,

Image 8

Our application should not scare the end user with displaying yellow pages and complex codes but it should be informative and end-user friendly.

Scenario 3: User inputs an integer but violates business logic by entering 5 or integer greater than 5.

Our case: No message is shown to the user, the page simply refreshes itself,

Ideal case: User should be shown a message that "no user exists with the specified ID, please enter another ID between 1 to 5", after getting this message user will no longer sit idle thinking about what is wrong with the web site, he will take some other fruitfull action.

To overcome such issue we can again decorate our code as:

C#
protected void btnSubmit_Click(object sender, EventArgs e)
   {
       try
       {

           string textValue = txtId.Text;
           int id;
           if (!Int32.TryParse(textValue, out id))
           {
               throw new ApplicationException("Please provide correct student id.");
           }

           if (id <= 0 || id >= 5)
           {
               throw new ApplicationException("No user exists with the specified id, please enter another id between 1 to 5");
           }

           string connectionString = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
           SqlConnection sqlConnection = new SqlConnection(connectionString);

           SqlCommand sqlCommand = new SqlCommand("Select StudentID,Fnamn,Enamn,Email,Login,Password from egStudent where StudentId=" +
              id.ToString(), sqlConnection);
           DataSet dataSet = new DataSet();
           SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
           sqlConnection.Open();
           sqlDataAdapter.Fill(dataSet);
           grdStudentView.DataSource = dataSet.Tables[0];
           grdStudentView.DataBind();
           sqlConnection.Close();
           sqlDataAdapter.Dispose();
       }
       catch (ApplicationException exception)
       {
           lblErrorDisplay.Visible = true;
           lblErrorDisplay.Text = exception.Message;
       }
   }

Therefore the output:

Image 9

The Exceptions discussed above were the Level 1 and Level 2 type exceptions.

Next comes Level 3. For level 3 type exceptions a special setup needs to be established, so that the exceptions could be handled as desired, simple playing with try catch blocks sometimes does not work with these kind of exceptions,

Scenario 4: A developer mistakingly writes a wrong query in select statement. Suppose he makes a typo and changes table name to egstudents (correct : egstudent). Let's see what happens.

C#
protected void btnSubmit_Click(object sender, EventArgs e)
 {
     try
     {

         string textValue = txtId.Text;
         int id;
         if (!Int32.TryParse(textValue, out id))
         {
             throw new ApplicationException("Please provide correct student id.");
         }

         if (id <= 0 || id >= 5)
         {
             throw new ApplicationException("No user exists with the specified id, please enter another id between 1 to 5");
         }

         string connectionString = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
         SqlConnection sqlConnection = new SqlConnection(connectionString);

         SqlCommand sqlCommand = new SqlCommand("Select StudentID,Fnamn,Enamn,Email,Login,Password from egStudents where StudentId=" +
            id.ToString(), sqlConnection);
         DataSet dataSet = new DataSet();
         SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
         sqlConnection.Open();
         sqlDataAdapter.Fill(dataSet);
         grdStudentView.DataSource = dataSet.Tables[0];
         grdStudentView.DataBind();
         sqlConnection.Close();
         sqlDataAdapter.Dispose();
     }
     catch (ApplicationException exception)
     {
         lblErrorDisplay.Visible = true;
         lblErrorDisplay.Text = exception.Message;
     }
 }

And so, the output:

Image 10

In this special case, once the site is up, it becomes hard for the developer to trace the code. Moreover the end user is once again exposed to the unwanted yellow page.

Cure: These kind of Level 3 exceptions need to be centralized (as discussed before in the article). We can write the piece of code in Global.asax on Application_Error event (handles application level errors), one can write the code to log the specific error and show end user a custom error page, to overcome panic situation.

Step1 : Add code to Global.asax,

C#
void Application_Error(object sender, EventArgs e)
   {
       Exception exception = Server.GetLastError();
       LoggError.Write(exception);

   }

Step2: Create a Custom Error Page, and define its path in web.config with a key value pair in appsettings

ErrorPage.aspx:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
<center>
<div><img src="ErrorPage1.jpg" alt="Error Page" /></div>
</center>
</body>
</html>

Page Path:

<appSettings>
  <add key="ErrorLog" value="~/ErrorLog.txt" />
</appSettings>

Step 3: Enable Custom error mode in web.config inside system.web node with path to your error page as default redirect,.

<customErrors mode="On" defaultRedirect="Error/ErrorPage.htm">
</customErrors>

Step 4: Add a class to your appCode folder, that logs the error into a text file.

C#
using System;
using System.Configuration;
using System.IO;
using System.Web;

    /// <summary>
    /// The Class Writes Exception and Error information into a log file named ErrorLog.txt.
    /// </summary>
public class LoggError
{
    /// <summary>
    /// Writes error occured in log file,if log file does not exist,it creates the file first.
    /// </summary>
    /// <param name="exception">Exception</param>
    public static void Write(Exception exception)
    {
        string logFile = String.Empty;
        StreamWriter logWriter;
        try
        {
            logFile = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["ErrorLog"].ToString());
            if (File.Exists(logFile))
                logWriter = File.AppendText(logFile);
            else
                logWriter = File.CreateText(logFile);
            logWriter.WriteLine("=>" + DateTime.Now + " " + " An Error occured : " +
                exception.StackTrace + " Message : " + exception.Message + "\n\n");
            logWriter.Close();
            throw exception;

        }
        catch (Exception e)
        {
            throw ;
        }
        finally
        {
            throw ;
        }
    }
}

Finally, when such error occurs, the user is displayed an error page as below:

Image 11

And for the sake of debugging and development, an actual error is logged in a text file (in my case located at root) as:

=>11/21/2011 7:42:02 PM  An Error occured :    at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.default_aspx.ProcessRequest(HttpContext context) in c:\Users\akhil.mittal\AppData\Local\Temp\Temporary ASP.NET Files\exceptionhandling\327c9c5b\2858bbb8\App_Web_iexkgkvc.2.cs:line 0
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) Message : System.Data.SqlClient.SqlException (0x80131904): Invalid object name 'egStudents'.
   at _Default.btnSubmit_Click(Object sender, EventArgs e) in d:\Akhil Mittal\Blogs\ExceptionHandling\Default.aspx.cs:line 56
   at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
   at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

The log gives full information about the type and source of exception.

There are many other ways to handle Level 3 Exceptions which we'll discuss in next coming articles, but to hit the floor running, this one is the beginning.

And last but not the least, the Finally block.

Finally Block

As the last clause in the try-catch statement a finally block can also be added. This block is used to clean up all the resources allocated in the try block and will always execute whether there is an exception or not. In the above scenarios for example, we can make use of this block to free SQL connection as.

sql connection as ,
sqlConnection.Close();
sqlDataAdapter.Dispose();

And thus the final code.

C#
protected void btnSubmit_Click(object sender, EventArgs e)
    {
        string textValue = txtId.Text;
        int id;
        string connectionString = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
        SqlConnection sqlConnection = new SqlConnection(connectionString);
        SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
        DataSet dataSet = new DataSet();
        try
        {
            if (!Int32.TryParse(textValue, out id))
                throw new ApplicationException("Please provide correct student id.");
            if (id <= 0 || id >= 5)
                throw new ApplicationException("No user exists with the specified id, please enter another id between 1 to 5");
            SqlCommand sqlCommand = new SqlCommand("Select StudentID,Fnamn,Enamn,Email,Login,Password from egStudents where StudentId=" +
           id.ToString(), sqlConnection);
            sqlDataAdapter = new SqlDataAdapter(sqlCommand);
            sqlConnection.Open();
            sqlDataAdapter.Fill(dataSet);
            grdStudentView.DataSource = dataSet.Tables[0];
            grdStudentView.DataBind();
        }
        catch (ApplicationException exception)
        {
            lblErrorDisplay.Visible = true;
            lblErrorDisplay.Text = exception.Message;
        }
        catch (Exception exception)
        {
            throw ;
        }
        finally
        {
            sqlConnection.Close();
            sqlDataAdapter.Dispose();
        }
    }

Conclusion

Now after successfully implementing the exception handling technique according to above discussed code and logic, we better know how and where to initiate exception handling in our code according to our requirements.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://codeteddy.com/
India India
Akhil Mittal is two times Microsoft MVP (Most Valuable Professional) firstly awarded in 2016 and continued in 2017 in Visual Studio and Technologies category, C# Corner MVP since 2013, Code Project MVP since 2014, a blogger, author and likes to write/read technical articles, blogs, and books. Akhil is a technical architect and loves to work on complex business problems and cutting-edge technologies. He has an experience of around 15 years in developing, designing, and architecting enterprises level applications primarily in Microsoft Technologies. He has diverse experience in working on cutting-edge technologies that include Microsoft Stack, AI, Machine Learning, and Cloud computing. Akhil is an MCP (Microsoft Certified Professional) in Web Applications and Dot Net Framework.
Visit Akhil Mittal’s personal blog CodeTeddy (CodeTeddy ) for some good and informative articles. Following are some tech certifications that Akhil cleared,
• AZ-304: Microsoft Azure Architect Design.
• AZ-303: Microsoft Azure Architect Technologies.
• AZ-900: Microsoft Azure Fundamentals.
• Microsoft MCTS (70-528) Certified Programmer.
• Microsoft MCTS (70-536) Certified Programmer.
• Microsoft MCTS (70-515) Certified Programmer.

LinkedIn: https://www.linkedin.com/in/akhilmittal/
This is a Collaborative Group

780 members

Comments and Discussions

 
Suggestion[My vote of 2] Catching exceptions is a start... Pin
Mad Myche2-Aug-16 9:34
Mad Myche2-Aug-16 9:34 
GeneralThank you!!! Pin
Cal Do27-Nov-15 22:26
Cal Do27-Nov-15 22:26 
GeneralRe: Thank you!!! Pin
Akhil Mittal29-Nov-15 18:07
professionalAkhil Mittal29-Nov-15 18:07 
QuestionThank you. Pin
udeep kansal10-Sep-13 20:16
professionaludeep kansal10-Sep-13 20:16 
AnswerRe: Thank you. Pin
Akhil Mittal10-Sep-13 20:46
professionalAkhil Mittal10-Sep-13 20:46 
GeneralExpensive Pin
dan_fish3-Sep-13 1:39
dan_fish3-Sep-13 1:39 
GeneralRe: Expensive Pin
Roman Ivantsov3-Sep-13 8:38
professionalRoman Ivantsov3-Sep-13 8:38 
GeneralMy vote of 5 Pin
Volynsky Alex30-Aug-13 0:12
professionalVolynsky Alex30-Aug-13 0:12 
GeneralRe: My vote of 5 Pin
Akhil Mittal30-Aug-13 22:20
professionalAkhil Mittal30-Aug-13 22:20 
GeneralRe: My vote of 5 Pin
Volynsky Alex31-Aug-13 2:44
professionalVolynsky Alex31-Aug-13 2:44 
GeneralMy vote of 3 Pin
BillWoodruff26-Aug-13 23:47
professionalBillWoodruff26-Aug-13 23:47 
GeneralMy vote of 4 Pin
V.Lorz26-Aug-13 20:26
V.Lorz26-Aug-13 20:26 
GeneralRe: My vote of 4 Pin
Akhil Mittal26-Aug-13 22:01
professionalAkhil Mittal26-Aug-13 22:01 
QuestionDoubt in this error handler. Pin
Santhoshpettacode22-Aug-13 21:43
professionalSanthoshpettacode22-Aug-13 21:43 
AnswerRe: Doubt in this error handler. Pin
Akhil Mittal26-Aug-13 17:53
professionalAkhil Mittal26-Aug-13 17:53 
GeneralMy vote of 3 Pin
Santhoshpettacode22-Aug-13 21:42
professionalSanthoshpettacode22-Aug-13 21:42 
GeneralMy vote of 5 Pin
pank.gupta14-Aug-13 6:55
pank.gupta14-Aug-13 6:55 
GeneralMy vote of 5 Pin
CodeLancer8-Aug-13 1:11
CodeLancer8-Aug-13 1:11 
GeneralMy vote of 5 Pin
Naushervan9-Jun-13 21:30
Naushervan9-Jun-13 21:30 
GeneralRe: My vote of 5 Pin
Akhil Mittal9-Jun-13 23:02
professionalAkhil Mittal9-Jun-13 23:02 
QuestionWrite Error Log or Exception Log into File in C# .NET Pin
World Traveler19-Mar-13 8:41
World Traveler19-Mar-13 8:41 
Generally we are not interested to show any type of application error to end user. Error logs are very important for collecting all error data generated by an application. It is more useful during an early or beta release of a product.
That’s why it is better to store any kind of exceptions in one place. This files can be send by email or others technology to developer. Time to time developer must analyze them and fix all the bugs without knowing clients. It will increase application performance.

A good solution with proper code about it is here: http://cybarlab.blogspot.com/2013/03/write-error-log-into-file-in-c-sharp.html
AnswerRe: Write Error Log or Exception Log into File in C# .NET Pin
Akhil Mittal19-Mar-13 17:04
professionalAkhil Mittal19-Mar-13 17:04 
GeneralRe: Write Error Log or Exception Log into File in C# .NET Pin
World Traveler19-Mar-13 19:31
World Traveler19-Mar-13 19:31 
QuestionNice article, but.. Pin
Eddy Vluggen22-Feb-13 0:28
professionalEddy Vluggen22-Feb-13 0:28 
GeneralMy vote of 5 Pin
Ruth Aanie21-Feb-13 20:44
Ruth Aanie21-Feb-13 20:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.