55

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));
        }

1 Answer 1

80

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Would the URL remain as it was originally...??? That is what I am trying to achieve by the method above i.e. if an error occurs the relevant view is sent back and the url remains the same/ the url does not change...
@Haroon, yes absolutely, it will remain the same. It will be the initial url that caused the exception, except that instead of a Yellow Screen of Death the custom view will be rendered.
may be my question is silly... but can anyone tell me where this OnException() (the above code) is to be placed in application. In any controller class or in global.ascx.cs. Where?
@bluesky OnException() is part of the controller class and can be overridden.
I found setting a few other properties such as view data (model of type HandleErrorInfo) and the response code was also helpful devproconnections.com/aspnet-mvc/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.