Best Exception Handling Techniques In .NET

Introduction

During application development, we have to adopt a manageable strategy for handling errors to keep the user’s experience pleasant and consistent. Microsoft .NET provides a list of best practices and guidelines to follow for writing less lines of code and effectively manage error and exception handling with more a logical approach of coding and designing the code modules. In this article, we will discuss best practices of exception handling, and guide you through few effective error handling strategies that you can use in your projects.

Exception Handling: the “Try-Catch-Finally” Block

Application errors are typically problems that are not expected. An exception is a type of error that occurs during the execution of an application. An application uses exception handling logic to explicitly handle the exceptions. During an exception, the current flow of the code is interrupted and handed back to a try catch-block the developer has written explicitly for the task. Following are the keywords in C# required for exception handling:

  • Try: A try block is used to encapsulate a region of code.
  • Catch: When an exception occurs, the catch block of code is executed.
  • Finally: The finally block will always execute. It allows you to deallocate memory and execute certain code whether an exception or not is thrown.
  • Throw: The throw keyword actually is used to create a new exception bubbled up to a try-catch-finally block.

The following exception handling example demonstrates how to properly use a try-catch-finally block for error handling.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PrjExceptionHandling
{
   public class Program
   {
      static void ProcessString(string str)
      {
         if (s == null)
         {
            throw new ArgumentNullException();
         }
      }
      public void Main(string[] args)
      {
         WebClient wc = null;
         string s = null;
         try
         {
            ProcessString(s);
            wc = new WebClient();
            var resultData = wc.DownloadString
               ("http://tapas-pal.blogspot.com/");
         }
         catch (ArgumentNullException ex)
         {
         }
         catch (WebException ex)
         {
         }
         catch (Exception ex)
         {
         }
         finally
         {
            wc?.Dispose();
         }
      }

   }
}

Exception handling block can utilize multiple C# catch statements for different types of exceptions. Catching specific types of exceptions can help developers debug and fix code quickly.

Using Exception Filters

A new feature in C# 6 was introduced—exception filters—that allow us to specify a conditional clause for each catch block. This allows developers even more control over catch blocks and the ability to further tailor how to handle specific exceptions.

By using exception filters, now you could choose which catch block to execute in a certain scenario. The following example demonstrates exception filters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PrjExceptionHandling
{
   public class Program
   {
      static void ProcessString(string str)
      {
         if (s == null)
         {
            throw new ArgumentNullException();
         }
      }
      public void Main(string[] args)
      {
         WebClient wc = null;
         string s = null;
         try
         {
            ProcessString(s);
            wc = new WebClient();
            var resultData =
               wc.DownloadString("http://tapas-pal.blogspot.com/");
         }

         catch (WebException ex) when (ex.Status ==
            WebExceptionStatus.ProtocolError)
         {

         }
         catch (WebException ex) when ((ex.Response as
            HttpWebResponse)?.StatusCode ==
            HttpStatusCode.NotFound)
         {

         }
         catch (WebException ex) when ((ex.Response as
            HttpWebResponse)?.StatusCode ==
            HttpStatusCode.InternalServerError)
         {

         }

         finally
         {
            wc?.Dispose();
         }
      }

   }
}

Centralized Exception Handling

For catching global exceptions in ASP.NET and MVC applications, an event named Application_Error exists. It is the global.asax file.

protected void Application_Error(Object sender, EventArgs e)
{
   Exception ex = Server.GetLastError();
   if (ex is ThreadAbortException)
      return;
   Logger.Error(LoggerType.Global, ex, "Exception");
   Response.Redirect("apperror.htm");
}

Application_Error could display a friendly error message or an error page. You even can write more important error details to log the exception details for further analysis.

.NET Custom Exception Types

When using a custom exception, we can write special code to handle the exception. By writing a custom C# exception, you can do custom handling of the exception during execution time; also, you can do custom monitoring around that custom exception type.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PrjExceptionHandling
{
   public class Program
   {

      public void Main(string[] args)
     {
         Employee objEmployee = null;

         try
         {
            objEmployee = new Employee();
            objEmployee.EmployeeName = "Tapas001";

            ValidateName(objEmployee);
         }
         catch (InvalidStudentNameException ex)
         {
            Console.WriteLine(ex.Message);
         }


         Console.ReadKey();
      }

      private static void ValidateName(Employee objEmployee)
      {
         Regex regex = new Regex("^[a-zA-Z]+$");

         if (!regex.IsMatch(objEmployee.EmployeeName))
            throw new InvalidStudentNameException
               (objEmployee.EmployeeName);

      }
   }

      class Employee
      {
         public int EmployeeID { get; set; }
         public string EmployeeName { get; set; }
      }

      [Serializable]
      class InvalidEmployeeNameException : Exception
      {
         public InvalidEmployeeNameException()
         {

         }

         public InvalidEmployeeNameException(string Employeename) :
            base(String.Format("Invalid Employee Name: {0}", name))
         {

         }

      }

   }
}

Using Exception Handling and Logging Libraries

.NET has a big list of logging and exception handling libraries so that you can record the exceptions that occurred. I would suggest logging your exceptions using popular frameworks such as Enterprise Library, NLog, Serilog, or log4net. All three frameworks give you the flexibility to log your exceptions to a file or database. Remember, every exception in your app should be logged. They are critical for finding problems in your code and are required for troubleshooting an exception.

Conclusion

Error handling is a broad topic, but I hope this article has explained the selective best practices developers can follow when writing C# code. That’s all for today. Happy Coding!

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read