MVC 5: Error Pages - Quick Solution

JanL@kentico.com[email protected] Czech RepublicMember, Administrator, Kentico Staff admin
edited February 2017 in Back-end Development

From the standards-based approaches described in the related discussion, we've tried to pick the right combination and create a simple yet flexible boilerplate code for displaying error pages in MVC 5 projects.

Here, you can read more about the standard framework methods. Also, in another discussion we describe a possible advanced way of displaying the error pages.

The solution consists of a controller base class with an overridden OnException method, a single strongly typed error view and an httpErrors attribute.

Let's see whether it would fit your needs.

The OnException method:

protected override void OnException(ExceptionContext filterContext)
{
    Exception ex = filterContext.Exception;
    ErrorViewModel errorViewModel = new ErrorViewModel();
    System.Net.HttpStatusCode statusCode = System.Net.HttpStatusCode.OK;

    // Signal to the other IIS/ASP.NET infrastructure about that the exception has already been handled by this code
    filterContext.ExceptionHandled = true;

    if (ex is System.Web.HttpException)
    {
        HttpException httpException = (HttpException)filterContext.Exception;
        Response.StatusCode = httpException.GetHttpCode();
        statusCode = (System.Net.HttpStatusCode)Response.StatusCode;
        Response.TrySkipIisCustomErrors = true;
    }
    else if (ex is KenticoCloud.Deliver.DeliverException)
    {
        KenticoCloud.Deliver.DeliverException deliverException = (KenticoCloud.Deliver.DeliverException)filterContext.Exception;
        Response.StatusCode = (int)deliverException.StatusCode;
        statusCode = (System.Net.HttpStatusCode)Response.StatusCode;
        Response.TrySkipIisCustomErrors = true;
    }
    else if (ex is System.ComponentModel.DataAnnotations.ValidationException)
    {
        errorViewModel.Title = "Validation failed";
        errorViewModel.Message = "When validating your input, something unexpected happened.";
    }
    else
    {
        errorViewModel.Title = "Whoops!";
        errorViewModel.Message = "An unexpected error has happened. Please try again or contact the admins.";
    }

    switch (statusCode)
    {
        case System.Net.HttpStatusCode.Unauthorized:
            errorViewModel.Title = "You shouldn't see this";
            errorViewModel.Message = "Looks like somebody forgot to add you to the entitled ones. Contact the admins.";
            break;
        case System.Net.HttpStatusCode.NotFound:
            errorViewModel.Title = "No matter what we do, we don't seem to be able to find it.";
            errorViewModel.Message = "Apparently someone moved things around and forgot to add a redirect rule. Bummer!";
            break;
            // ...
    }

    filterContext.Result = View("ErrorEnhanced", errorViewModel);
}

The view model of the error:

public class ErrorViewModel
{
    public string Title { get; set; }
    public string Message { get; set; }
}

The strongly typed view:

@model WebApplication.ErrorViewModel

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Error";
}

<h1 class="text-danger">@Html.DisplayFor(m => m.Title)</h1>
<h2 class="text-danger">@Html.DisplayFor(m => m.Message)</h2>

The following list contains framework exceptions that we think it's worth handling:

Apart from that, the code should be accompanied by a couple of httpErrors attributes in the web.config file. They should cover the most significant HTTP status codes that could be returned by various IIS modules.

Pros:

  • Simplicity
  • Convenient MVC-way of re-routing to the error page
  • Covered by the catch-all httpErrors attribute for static files and other IIS modules' error codes

Cons:

  • Although suitable for serving Deliver content, this method may not be suitable for more advanced controller actions
  • Probably not quite fit for usage with asynchronous actions

Questions to discuss

These are the things we'd love you to tell us:

  • What is your experience with the error-handling methods predefined in IIS/ASP.NET/MVC?
  • Do you use them (build on top of them) as Microsoft expected?
  • What are the main reasons for you to use/not to use them?
  • In the above list of exceptions, do you miss any?
  • Which of the exceptions inheriting from System.SystemException would you handle?

Feel free to discuss the topic here! We'd love to hear if this is what you'd use in your projects. Then, we could write an article and discuss how we can improve the Deliver .NET SDK, together with the community.

Comments

  • JanL@kentico.com[email protected] Czech RepublicMember, Administrator, Kentico Staff admin

    Hello, you may have noticed a change in the code. I've rewritten it to get rid of the switch statement. The semantics of switch are great for such logic but it required me to use 'stringly' typed identification of types of exceptions. Now the code is better, just slightly more chatty.

Sign In or Register to comment.