Exception Handling

Oct 03


When creating your own widgets one thing you don't want is if it throws an error to 500 the whole page. Maybe you do? This post is for those that don't want that but prefer to display something a bit more friendly and are looking for help tracking those, 'only happens in production with a random customer', errors.

Nothing too exciting to start with. We will be using the MVC Controller event handler OnException. By handling the error at the controller level it means that it won't bubble up higher and out of this widget's context and affect the rest of the page.

I usually create a 'BaseController' controller and put all my common and shared code for my controllers into here, such as this handling exceptions event.

But what you may be interested in are some steps for handling the exception, returning some user-friendly HTML to replace what the widget would have rendered. And... a friendly code, unique to this event allows you to search and find the exact exception in your error logs.

The Controller

First, override the method.

protected override void OnException(ExceptionContext filterContext)

The first bit of code is to check that this exception actually hasn't already been handled. This can arise when another exception has done a redirect. There are potentially other cases but if you handle an already handled exception you may end up in a circular exception handling scenario.

if (filterContext != null && filterContext.ExceptionHandled)

Next, check that an actual exception has come through else create a new one to continue. I don't know how this could happen but it was mentioned by others and if it does happen I will know exactly what has taken place when looking in my logs rather than being totally perplexed.

var ex = filterContext?.Exception ?? new Exception("No further information exists.");

Now for something interesting. I want to be able to track this exception by sending the user a code that they can quote when they contact me. It is up to you what that code will look like but I have gone for a random five-digit number. Five because it should be easy for them to remember and note down yet unlikely to be generated twice in a short period of time. I then create a new exception and use this identifier in the title to wrap the original exception. Then log it.

Random random = new Random();
    Int32 userReportingCode = random.Next(10000, 99999);
    ApplicationException appExcept = new ApplicationException(String.Format("Controller Exception : {0}"userReportingCode), ex);

What I want to do next is push this information to a generic custom error view. To do this I set the Result property of the ExceptionContext.

In development, I actually want the error straight away. I don't want to have to search a log so I do a test and populate another field in my model.

ControllerErrorViewModel viewModel = new ControllerErrorViewModel(userReportingCode);
if (ConfigurationManager.AppSettings["Environment"] == "local")
    viewModel.ErrorMessage = ex.Message;
filterContext.Result = View("~/ResourcePackages/northcote/Mvc/Views/Shared/ControllerError.cshtml"viewModel);

The View

In my view, I have some generic HTML to populate the space of the widget and display the error code for user to report back to me.

<div class="center callout alert" role="alert">
    <h3 class="maroon">Uh-O<span aria-hidden="true"> :-(</span></h3>
    @if (String.IsNullOrEmpty(Model.ErrorMessage))
        <h4 class="maroon">We encountered an error here</h4>
        <p class="text-center">We have been notified and will look into what happened.<br />
        If you continue to see this error please contact us and quote this error id - @Model.ErrorId</p>

The Result

Just part of my page is broken.

Controller Error

Darrin Robertson - Sitefinity Developer

Thanks for reading and feel free to comment - Darrin Robertson

If I was really helpful and you would buy me a coffee if you could, yay! You can.

Leave a comment
Load more comments

Make a Comment

recapcha code