Rules for Error Handling

Since 1990, SSW has supported the developer community by publishing all our best practices and rules for everyone to see. 

If you still need help, visit SSW Consulting Services ​and book in a consultant.​​

Hold on a second! How would you like to view this content?
Just the title! A brief blurb! Gimme everything!
  1. Do you always avoid On Error Resume Next? (VB Only)

    ​​Never use On Error Resume Next in VB (and VB.NET) projects.

    If an error occurred, On Error Resume Next will hide the error and things can go very haywire! In .NET, stop using the On Error syntax and use the try-catch exception syntax for better structural exception handling.

    In VB/VBA you should use On Error Resume Next with line of comment and after an offending line of code there should be statement On Error GoTo 0 to reset Errors collection.

    Private Sub cmdSelect_Click()
        Dim varTemp As Variant
        On Error Resume Next
        varTemp = columnADOX.Properties("RelatedColumn").Value
            .
            ....many lines of code...
            .
        intRoutesPerDay = 2
        End Sub
    
    Bad Example – Bad code
    Private Sub cmdSelect_Click()
        Dim varTemp As Variant
        On Error Resume Next
        'Sometimes there is no related column value
        varTemp = columnADOX.Properties("RelatedColumn").Value
        On Error GoTo 0
    
        .
        ....continuing code...
        .
        End Sub
    
    Good Example – Good code

    We have a program called SSW Code Auditor to check for this rule.

  2. Do you catch and re-throw exceptions properly?

    ​A good catch and re-throw will make life easier while debugging, a bad catch and re-throw will ruin the exception's stack trace and make debugging difficult.

    catch {} 
    (Never use an empty catch block. Do something in the block or remove it.)
    
    catch (SomeException) {} 
    (Never use an empty catch block. Do something in the block or remove it.)
    
    catch { throw; } 
    
    (Never use an empty catch block. Do something in the block or remove it.)
    catch (SomeException) { throw; }
    (Never use an empty catch block. Do something in the block or remove it.)
    catch (SomeException ex) { throw ex; } (Never re-throw exceptions by passing the original exception object. Wrap the exception or use throw; instead.) catch (SomeException ex) { someMethod(); throw ex; } (Never re-throw exceptions by passing the original exception object. Wrap the exception or use throw; instead.)
    Bad Example - Bad code
    catch (SomeException ex) 
    { 
         someMethod(); 
         throw; 
    }
    
    catch (SomeException ex) 
    { 
         someMethod(); 
         SomeOtherException wrapperEx = new SomeOtherException("This is a wrapper exception", ex);
         throw wrapperEx; 
    }
    
    Good Example - Good code

    We have a program called SSW Code Auditor to check for this rule.

  3. Do you catch exceptions precisely?

    ​​In the try and catch block, if you always catch for normal Exception you will never know where the true problem is. When using try you should always expect some exception may happen, so in our code we always catch the specific exceptions.

    try 
    { 
         connection.Open();
    }
    catch (Exception ex) 
    { 
         return ex.ToString ();
    }
    
    Bad code – Catching the general Exception
    try 
    { 
         connection.Open(); 
    }
    catch (InvalidOperationException ex) 
    { 
         return ex.ToString(); 
    }
    catch (SqlException ex) 
    { 
         return ex.ToString(); 
    }
    
    Good code - Catch with specific Exception

    We have a program called  SSW Code Auditor to check for this rule.

  4. Do you know that you should never throw an exception using System.Exception?

    ​​​While everyone knows that 'catch (Exception ex)' is bad, no one has really noticed that 'throw new Exception()' is worse.

    System.Exception is a very extensive class, and it is inherited by all other exception classes. If you throw an exception with the code 'throw new Exception()', what you need subsequently to handle the exception will be the infamous 'catch (Exception ex)'.

    As a standard, you should use an exception class with the name that best describes the exception's detail. All exception classes in .NET Framework follow this standard very well. As a result, when you see exceptions like FileNotFoundException or DivideByZeroException, you know what's happening just by looking at the exception's name. The .NET Framework has provided us a comprehensive list of exception classes that we can use. If you really can't find one that is suitable for the situation, then create your own exception class with the name that best describes the exception (e.g.​: EmployeeListNotFoundException).

    Also, System.ApplicationException should be avoided as well unless it's an exception related to the application. While it's acceptable and should be used in certain cases, be aware that using it broadly will be just as bad as 'throw new Exception()'.

    We have a program called SSW Code Auditor to check for this rule.

  5. Do you present the user with a nice error screen? (Web Only)

    ​​​Your users should never see the “yellow screen of death” in ASP.NET. Errors should be caught, logged and a user-friendly screen displayed to the user.

    This last part is done by specifying the customErrors element in the web.config file.

    This will activate ASP.NET’s built in error page (e.g. MVC’s HandleErrorAttribute filter) which can then be customized to suit your application.


    Figure: Bad Example – Yellow Screen of Death
    Figure: Good Example - Default ASP.NET MVC custom error page


    ​However, as a developer you still want to be able to view the detail of the exception in your local development environment. Use the below setting in your Web Application's web.config file to view the yellow screen locally but present a nice error screen to the user.

    14-08-2014-2-47-50-PM-compressor.png​​​

    ​​​Figure: Good Example - Don't hide the yellow screen of death in the local environment


  6. Do you use an analytics framework to help manage exceptions?

    ​The ability to see the overall health (performance counters, exceptions, data usages, page hit counts etc.) of your application ensures you are well in control of it and have all the necessary information at your hands to action any bugs or performance issues. An analytics framework allows you to do all of that in a consistent and centralised manner. 
    ​​An analytics framework puts you in control of your application and allows you to do the following:
    • Capture, log and action exceptions
    • Analyse performance issues and identify bottlenecks
    • Track application usage down to individual components
    • View and create performance reports
    • Analyse user demographics
    There are a number of existing Analytics frameworks available on the market, so there is no need to "re-invent the wheel". Why would you write your own if someone else has already taken the trouble to do it? We recommend using one of these frameworks or services​:
    Each one of those frameworks has a fairly extensive set of tools available and are easy to integrate into your application.​
  7. Do you use LadyLog?

    ​Your users should never see the "unhandled exception" message in Windows Forms, WPF and Silverlight. You should always log errors somewhere (preferably a SQL database).

    Figure: Bad example - your users should never have unhandled exceptions in Windows Forms

    LadyLog is a Windows UI for your application that allows users to Log meaningful errors.

    Figure: Good example - your users get a nice professional error reporting window

    See SSW .NET Toolkit - LadyLog.

    We have a program called SSW Code Auditor to check for this rule.

    Read more about Do you use LadyLog?
  8. Do you use the best exception handling library?

    ​​When developing software, exceptions are a fact-of-life you will need to deal with. Don't reinvent the wheel, use an existing exception handling library or service.

    ​​​The best exception handling service is Application Insights for ​Visual Studio Online​, but if you can't use that, then use ELMAH​.

    Your users should never see the “yellow screen of death” in ASP.NET, or the “unhandled exception” message in a Windows application. Errors should always be caught and logged – preferably in a SQL database.​


    At SSW we use Application Insights for Visual Studio Online.

    Application Insights will tell you if your application goes down or runs slowly under load. If there are any uncaught exceptions, you’ll be able to drill into the code to pinpoint the problem. You can also find out what your users are doing with the application so that you can tune it to their needs in each development cycle.  

    If Application Insights for Visual Studio Online is not available we use ELMAH when developing web applications. From its NuGet page:

    ELMAH with initial configuration for getting started quickly. ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

    If you are still developing Windows applications, then SSW Exception Logger is the one to use. Read SSW .NET Toolkit – LadyLog User Guide.

    ELMAH can be easily added to your application from NuGet, and it configures itself.

    2014-09-08_10-56-57-compressor.png
    Figure: Add ELMAH to your web application from NuGet

    See also Do you use the best middle tier .Net libraries?

  9. Do you use the best trace logging library?

    Did you know that writing your own logging infrastructure code wastes time? You should use a logging library, and the best logging library is Serilog.

    Serilog is a NuGet package that can be included in any .NET application, is easy to configure, supports many different output targets, has great performance, and allows for runtime changes to configuration. Serilog also supports full integration with log4net so is easy to use with any older codebase using log4net.

    Serilog supports all the log4net concepts of logging at different levels of importance (e.g. Error, Warning, Information) and having different logs for different components of your application (e.g. a Customer Log and an Order Log).

    Serilog's main advantage over previous loggers is its ability to serialize and log full .net objects rather than just strings. Serilog also has a powerful, nested context system allowing log events to be grouped by request, operation etc. 

    Serilog has the concept of "sinks": pluggable modules that can consume, store and/or act on logging events. The most powerful sink is Seq - a web application that allows the user to perform complex search queries on incoming log data in real time.

    Other sinks allow you to:

    • ​save logs to a file
    • export to log4net (and subsequently use any log4net appender)
    • save to a database
    • export to Application Insights, New Relic and many other APM platforms
    Many other sinks are available as described here: https://github.com/serilog/serilog/wiki/Provided-Sinks​
    Figure: Bad Example - Using Debug or Trace for logging, or writing hard coded mechanisms for logging does not allow you to configure logging at runtime
    Figure: Bad Example - Roll your own logging components lack functionality, and have not been tested as thoroughly for quality or performance as log4net


    serilog.png
     

    Figure: Good Example - Using serilog allows persisting structured log data to multiple stores, querying that data intelligently and requires less work to install and configure than a roll-you-own logger, and provides many more features

    seq2.png
     

    Figure: Good Example - Seq provides a powerful UI for searching and viewing your structured logs

    Serilog should be added to your project via the NuGet package manager.

    See also Do you use the best middle tier .NET​ libraries?