Asp.net mvc override OnException in base controller keeps propagating to Application_Error

59,849

The following should work:

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled)
    {
        return;
    }
    filterContext.Result = new ViewResult
    {
        ViewName = "~/Views/Shared/Error.aspx"
    };
    filterContext.ExceptionHandled = true;
}

Also make sure that no exception is thrown in this method or it will propagate to Application_Error.

Share:
59,849
Haroon
Author by

Haroon

Web Developer/Software Developer, C#, ASP.NET, SQL, Javascript, CSS, (X)HTML

Updated on July 14, 2020

Comments

  • Haroon
    Haroon almost 4 years

    I am trying to return a view not issue a redirect to the user based on certain errors that could occur from my application, I want to handle the errors + log them inside my base controller, I do not want the error to propagate up to my Global.asax - Application_Error() method as I want this method to handle any other errors inside my app e.g. user enters a bogus URL, has anyone found a way around this?

    NOTE: I have left my commented code as I had a workaround for some issues, this also shows I have multiple exceptions to possible handle...

    EDIT: If I issue a RedirectToAction within this OnException override everything works as expected, but I only want to return the view and no redirection...

    My base controller method is:

        protected override void OnException(ExceptionContext filterContext)
        {
            //dont interfere if the exception is already handled
            if (filterContext.ExceptionHandled)
                return;
    
            //let the next request know what went wrong
            filterContext.Controller.TempData["exception"] = filterContext.Exception;
    
            //log exception
            _logging.Error(User.Identity.Name, ExceptionHelper.BuildWebExceptionMessage(filterContext.Exception));
    
    
            //set up redirect to my global error handler
            //if (filterContext.Exception.GetType() == typeof(NoAccessException))
            //    filterContext.Result = View(new RouteValueDictionary
            //    (new { area = "", controller = "Error", action = "PublicError" }));
    
            //else {
            //Only return view, no need for redirection
            filterContext.Result = View(new RouteValueDictionary
            (new { area = "", controller = "Error", action = "NoAccess" }));
            //}
            //advise subsequent exception filters not to interfere and stop
            // asp.net from showing yellow screen of death
            filterContext.ExceptionHandled = true;
    
            //erase any output already generated
            filterContext.HttpContext.Response.Clear();
    
            //base.OnException(filterContext);
        }
    

    This method should handle any other errors that could appear in my app, I do not want the errors above being handled inside my Application_Error()

    protected void Application_Error()
            {
    
                Exception exception = Server.GetLastError();
                // Log the exception.
    
                var logger = Container.Get<ILoggingService>();
                logger.Error(User.Identity.Name, ExceptionHelper.BuildWebExceptionMessage(exception));
    
                Response.Clear();
    
                HttpException httpException = exception as HttpException;
    
                RouteData routeData = new RouteData();
                routeData.Values.Add("controller", "Error");
    
                //if (httpException == null)
                //{
                routeData.Values.Add("action", "PublicError");
                //}
                //else //It's an Http Exception, Let's handle it.
                //{
                //    switch (httpException.GetHttpCode())
                //    {
                //        case 404:
                //            // Page not found.
                //            routeData.Values.Add("action", "HttpError404");
                //            break;
                //        case 500:
                //            // Server error.
                //            routeData.Values.Add("action", "HttpError500");
                //            break;
    
                //        // Here you can handle Views to other error codes.
                //        // I choose a General error template  
                //        default:
                //            routeData.Values.Add("action", "General");
                //            break;
                //    }
                //}
    
                // Pass exception details to the target error View.
                routeData.Values.Add("error", exception);
    
                // Clear the error on server.
                Server.ClearError();
    
                // Avoid IIS7 getting in the middle
                Response.TrySkipIisCustomErrors = true;
    
                // Call target Controller and pass the routeData.
                IController errorController = new ErrorController();
                errorController.Execute(new RequestContext(
                     new HttpContextWrapper(Context), routeData));
            }