Glenn Ferrie
Glenn Ferrie

Reputation: 10410

Override `HandleErrorAttribute` in ASP.NET MVC

I want to override the HandleErrorAttribute with a new version called something like HandleErrorsWithLogging. Essentially, I want it to log the unhandled exception to my log file and then proceed with the typical 'Redirect to ~/Shared/Error' functionality you get with HandleError.

I am already adding HandleError to all my actions in the global.asax

Is this the best approach or is there some easier way to gain access to that unhandled exception for logging purposes? I had also though about an Ajax call on the Error view itself.

Upvotes: 2

Views: 3793

Answers (2)

Flavia
Flavia

Reputation: 561

You can create a custom filter that inherits from FilterAttribute and implements IExceptionFilter. Then register it in global.asax.cs. Also you must enable custom errors handling in the web.config:

<customErrors mode="On"/>  


    public class HandleErrorAndLogExceptionAttribute : FilterAttribute, IExceptionFilter
        {
            /// <summary>
            /// The method called when an exception happens
            /// </summary>
            /// <param name="filterContext">The exception context</param>
            public void OnException(ExceptionContext filterContext)
            {
                if (filterContext != null && filterContext.HttpContext != null)
                {
                    if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
                    {
                        // Log and email the exception. This is using Log4net as logging tool
                        Logger.LogError("There was an error", filterContext.Exception);

                        string controllerName = (string)filterContext.RouteData.Values["controller"];
                        string actionName = (string)filterContext.RouteData.Values["action"];
                        HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

                        // Set the error view to be shown
                        ViewResult result = new ViewResult
                        {
                            ViewName = "Error",
                            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                            TempData = filterContext.Controller.TempData
                        };

                        result.ViewData["Description"] = filterContext.Controller.ViewBag.Description;
                        filterContext.Result = result;
                        filterContext.ExceptionHandled = true;
                        filterContext.HttpContext.Response.Clear();
                        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
                    }
                }
            }

Upvotes: 6

Darin Dimitrov
Darin Dimitrov

Reputation: 1039110

Overriding the HandleError attribute is indeed one approach into handling this. There are other approaches as well. Another approach is to use ELMAH which will take care of this so that you shouldn't worry about logging. Yet another approach consists in removing any HandleError global filters from Global.asax and subscribe for the Application_Error which is more general than HandleError as it will intercept also exceptions that happen outside of the MVC pipeline. Here's an example of such handling.

Upvotes: 1

Related Questions