4

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?

Bob Tway
  • 9,301
  • 17
  • 80
  • 162
  • Check [this](http://stackoverflow.com/questions/960280/asp-net-mvc-controller-onexception-not-being-called) ? – Berkay Yaylacı Apr 05 '17 at 10:42
  • @Berkay that's not the issue at all. OnException is certainly being called. But when it redirects to the error controller, the Error action isn't being called. – Bob Tway Apr 05 '17 at 10:46
  • You are setting Result Property to an instance of `ViewResult` which will return the view specified by the name. You can check by putting different view name in ` ViewName = "Error",`. It should say that viewname is not found.` What you basically need to do is redirect to the controller action `Error` of conttroller `ErrorController`. – Chetan Apr 05 '17 at 10:48
  • @ChetanRanpariya Surely that's what the code is doing? The line filterContext.RouteData.Values["controller"] = "Error" should direct to the ErrorController and the ViewName should go to the error view? – Bob Tway Apr 05 '17 at 10:54
  • 2
    Might be you have to try like dis way `filterContext.Result = this.RedirectToAction("Error", "Error");` – Curiousdev Apr 05 '17 at 12:31
  • @Curiousdev That's it. If you want to post it as an answer, I'll accept. I'd still like to know how this is happening, mind :) – Bob Tway Apr 05 '17 at 13:42

1 Answers1

2

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.

Curiousdev
  • 5,668
  • 3
  • 24
  • 38