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
?