Lessons in this course (10)

9. Error handling, custom error pages and logging in MVC 5

Intermediate★ Must knowLesson 9 of 10

Layers of error handling:

  1. try/catch in actions/services for expected failures (show a validation message, return 404/409).
  2. Exception filters — [HandleError(ExceptionType = typeof(DbUpdateException), View = "DatabaseError")] or a custom IExceptionFilter that logs and shows a view (only for exceptions inside MVC actions/results).
  3. Controller.OnException override — per-controller handling.
  4. Application_Error in Global.asax — catches everything else (routing errors, errors outside MVC), log and redirect.
  5. web.config — customErrors (ASP.NET) and httpErrors (IIS) for friendly pages for 404/500.
csharp
public class GlobalExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext ctx)
    {
        Log.Error(ctx.Exception, "Unhandled error in {Controller}", ctx.RouteData.Values["controller"]);
        if (ctx.HttpContext.Request.IsAjaxRequest())
        {
            ctx.Result = new JsonResult { Data = new { error = "Something went wrong" }, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            ctx.HttpContext.Response.StatusCode = 500;
        }
        else ctx.Result = new ViewResult { ViewName = "Error" };
        ctx.ExceptionHandled = true;
        ctx.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}
xml
<system.web>
  <customErrors mode="On" defaultRedirect="~/Error">
    <error statusCode="404" redirect="~/Error/NotFound" />
  </customErrors>
</system.web>
<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" /><error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
  </httpErrors>
</system.webServer>