Bob Tway
Bob Tway

Reputation: 9603

Why do exceptions handled in MVC OnException not hit error controller actions?

As a catch-all means of handling errors, I added this to the BaseController in my MVC web application.

public class BaseController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        _logger.Error(filterContext.Exception, "Website error page displayed.");

        TempData["ErrorMessage"] = "Unspecified error - please contact support";
        filterContext.RouteData.Values["controller"] = "Error";
        filterContext.Result = new ViewResult
        {
            ViewName = "Error",
        };

        filterContext.ExceptionHandled = true;
    }
}

And I have a dedicated ErrorController that looks like this:

public class ErrorController : BaseController
{
    [AllowAnonymous]
    public ActionResult Error()
    {
        string errorMessage = "There has been an error";
        if(TempData["ErrorMessage"] != null)
        {
            errorMessage = TempData["ErrorMessage"].ToString();
        }

        Logger.Warn("Error error page displayed with message {0}", errorMessage);
        ViewBag.ErrorMessage = errorMessage;
        return View("Error");
    }
}

When an error is handled in part of the application and the user is redirected to the error page, this works fine:

if (!await UserManager.IsEmailConfirmedAsync(user.Id))
{
    TempData["ErrorMessage"] = "You must have a confirmed email to log on.";
    return RedirectToAction("Error", "Error");
}

However, if the error is unhandled and is routed through OnException on BaseController then the error View renders as expected, but the Error action on the controller is never hit. The error message assumes the default value, and breakpoints in the action don't get tripped.

Why is this? How can I correctly invoke the controller action from OnException?

Upvotes: 4

Views: 1837

Answers (1)

Curiousdev
Curiousdev

Reputation: 5778

As you go to defination and see filterContext.Result is type of ActionResult which is a return type compatible with both ViewResult and RedirectToRouteResult.

How ViewResult functions is it just Renders a specified view to the response stream.

At the other side RedirectToAction returns a RedirectToRouteResult which is also derived from ActionResult and it Performs an HTTP redirection to a URL that is determined by the routing engine, based on given route data.

So in your case you need redirection so that's the reason you have to use RedirectToAction("Error", "Error"); as it will return a RedirectToRouteResult and redirect to the route you have specified.

Upvotes: 2

Related Questions