Global exception logging in ASP.NET MVC 4


This post is an aggregation of various posts found on the web which aim to address the issue of global logging of exceptions as well as the display of nice “error” pages in ASP.NET MVC 4.

As developers, we do spend quite a bit of time debugging applications. However, implementing error logging is often an afterthought of the development process and more often than not the solutions, although functional, are poorly executed.

Display nice error page to user

Here’s a very nice page which explains how to get a nice custom error page. Moreover, it explains how you can log exceptions (We’ll come back to why the suggestions provided are not optimal).

What is missing from that post is what happens if we try to go to a non existent page and the answer is that the user, with the code provided in the post, will see:

404Now, for me, when I was a beginner, this was confusing. The source of confusion comes from the fact that “error” and “exception” are often used interchangeably. The web.config entry:

<customErrors mode="On">
</customErrors>

as it currently stands will deal with exceptions i.e. whenever there is an exception, the “Error.cshtml” page will be invoked. (If you want to know how this happensthen look at his page.)

However, in the wider meaning of error, we get the page shown above. The way to show a custom error page in that case is to add the following in the web.config file:

<customErrors mode="On">
  <error statusCode="404" redirect="~/HttpError/NotFound404"/>
</customErrors>

The “redirect” path is in the format Controller/Action. Hence, it will come as no surprise that the following controller:

using System.Web.Mvc;

namespace MVC4_WebApplication_InternetApplication.Controllers
{
    public class HttpErrorController : Controller
    {
        public ActionResult NotFound404()
        {
            return View();
        }
    }
}

and the corresponding view:

<hgroup>
    <h1>Error.</h1>
    <h2>The page you are trying to access doesn't exist. Please ensure that you have typed in the correct address.</h2>
</hgroup>

Once this is in place, a custom error page will be shown to the user. You might, at this point, want to show appropriate error pages for the various Http status codes wherever suitable.

Exception logging

The point of exception logging, in my view, is to help with debugging issues and it is really valuable in production environments or environments where you have limited access to.

Now I’m going to explain why the error logging strategy given in the post above isn’t optimal. In the case whereby the OnException method of Controller is overriden, the code isn’t DRY as Mark Seeman explains. His solution does work but in ASP.NET MVC 4, Global Error Handling is taken care of for us:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

Mark Seeman also has another post detailing how to perform logging of exceptions. Based upon his solution, I also created a decorator class:

public class LoggingExceptionFilter : IExceptionFilter
{
    private readonly IExceptionFilter _filter;

    private readonly ILogWriter _logWriter;

    public LoggingExceptionFilter(IExceptionFilter filter,
        ILogWriter logWriter)
    {
        if (filter == null)
        {
            throw new ArgumentNullException("filter");
        }

        if (logWriter == null)
        {
            throw new ArgumentNullException("logWriter");
        }

        _filter = filter;
        _logWriter = logWriter;
    }

    public void OnException(ExceptionContext filterContext)
    {
        _logWriter.WriteError(filterContext.Exception);
        _filter.OnException(filterContext);
    }
}

and changed the class “FilterConfig” to:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new LoggingExceptionFilter(new HandleErrorAttribute(), new NLogWriter()));
    }
}

where NLogWriter is:

public class NLogWriter : ILogWriter
{
    private static readonly Logger _logger = LogManager.GetCurrentClassLogger();

    public void WriteError(Exception exception)
    {
        _logger.Error("An exception occurred with the following message {0}\n and the following stacktrace: {1}", exception.Message, exception.StackTrace);
    }
}

The code is available on GitHub.

Advertisements
Posted in .NET, ALT.NET, ASP.NET MVC, NLog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: