Handling all exceptions in controllers using the attribute

    We all know that in ASP.NET MVC there is such an attribute HandleErrorAttribute, which as stated in MSDN
    Represents an attribute used to handle an exception raised by an action method.

    But nowhere, in the same MSDN it is not said ( poke me with your nose, give the link where it is written, if I looked) that it only handles exceptions that set the server’s response code to 500.

    Looking at the source code is HandleErrorAttributeeasy to verify. The following lines are there:

    // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
    // ignore it.
    if (new HttpException(null, exception).GetHttpCode() != 500) {

    I don’t know about you, but it’s more convenient for me when an exception occurs that users see a special page for this, and not the “yellow page of death” or even how the browser displays a standard page for it with the server response code (it depends on the settings in Web.config, but more on that later).

    Creating your own analogue HandleErrorAttribute

    So, we found out that the standard HandleErrorAttributeis not suitable for us, well, let's create our own.

    You can, of course, create a class by inheriting it from the interface IExceptionFilter, but in general, we are satisfied with the standard behavior HandleErrorAttributeif it handled all exceptions. And since almost everything suits us, our class will inherit from the objectionable to us HandleErrorAttribute.

    public class HandleAllErrorAttribute : HandleErrorAttribute
        public override void OnException(ExceptionContext filterContext)
            if (filterContext == null)
                throw new ArgumentNullException("filterContext");
            // If custom errors are disabled, we need to let the normal ASP.NET exception handler
            // execute so that the user can see useful debugging information.
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            Exception exception = filterContext.Exception;
            if (!ExceptionType.IsInstanceOfType(exception))
            string controllerName = (string)filterContext.RouteData.Values["controller"];
            string actionName = (string)filterContext.RouteData.Values["action"];
            HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
            filterContext.Result = new ViewResult
                ViewName = View,
                MasterName = Master,
                ViewData = new ViewDataDictionary(model),
                TempData = filterContext.Controller.TempData
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.StatusCode = new HttpException(null, exception).GetHttpCode();
            // Certain versions of IIS will sometimes use their own error page when
            // they detect a server error. Setting this property indicates that we
            // want it to try to render ASP.NET MVC's error page instead.
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

    To begin with, I will say that this is standard code HandleErrorAttribute, with the exception of a few lines that check for HttpStatusCode.

    Actually what he does:
    • Checks input parameters for validity
    • Checks if included customErrors
    • Fills a class with data HandleErrorInfo
    • Creates a new one ViewResult, fills with data and assigns instead of the current
    • Clears server errors and sets the server response code

    Our class is ready, now we will replace the standard attribute with ours. We do this through global filters so that we don’t write it to every controller or controller action. In this case, this is not critical, but in reality it can come in handy. So, we go to Global.asax.cs and set instead of the standard filter, our just created attribute:

    filters.Add(new HandleAllErrorAttribute());


    Now, to make sure that our filter works and passes the necessary data to View, we ’ll slightly modify the standard ~ / Views / Shared / Error.cshtml :

    @model System.Web.Mvc.HandleErrorInfo
        ViewBag.Title = "Error";

    Sorry, an error occurred while processing your request.


    And add the following line to the section in Web.config (which is located in the root) System.Web:

    With this line, we enable custom error handling, more precisely, custom error pages.

    Now we need to throw an exception, I will do this in the action of the standard controller (created by the studio):

    public ActionResult About()
        throw new HttpException(403, "Доступ запрещён!");
        return View();

    All! We start the project, go to the "About" section and see that our attribute worked correctly.

    Also popular now: