Let's say I put the following code somewhere in a Master page in my ASP.NET MVC site:
throw new ApplicationException("TEST");
Even with a [HandleError] attribute placed on my controller, this exception still bubbles up. How can I deal with errors like this? I would like to be able to route to an Error page and still be able to log the exception details.
What is the best way to deal with something like this?
Edit: One solution I was considering would be to add a a new controller: UnhandledErrorController. Can I put in an Application_Error method in Global.asax and then redirect to this controller (where it decides what to do with the exception)?
Note: the defaultRedirect in the customErrors web.config element does not pass along the exception info.
As MVC is built on top of asp.net you should be able to define a global error page in web.config, just like you could in web forms eg.
<customErrors mode="On" defaultRedirect="~/ErrorHandler" />
Enable customErrors:
<customErrors mode="On" defaultRedirect="~/Error">
<error statusCode="401" redirect="~/Error/Unauthorized" />
<error statusCode="404" redirect="~/Error/NotFound" />
</customErrors>
and redirect to a custom error controller:
[HandleError]
public class ErrorController : BaseController
{
public ErrorController ()
{
}
public ActionResult Index ()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return View ("Error");
}
public ActionResult Unauthorized ()
{
Response.StatusCode = (int)HttpStatusCode.Unauthorized;
return View ("Error401");
}
public ActionResult NotFound ()
{
string url = GetStaticRoute (Request.QueryString["aspxerrorpath"] ?? Request.Path);
if (!string.IsNullOrEmpty (url))
{
Notify ("Due to a new web site design the page you were looking for no longer exists.", false);
return new MovedPermanentlyResult (url);
}
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View ("Error404");
}
}
You can create a Filter that looks for an Exception in the OnActionExecuted
method:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class WatchExceptionAttribute : ActionFilterAttribute {
public override void OnActionExecuted(ActionExecutedContext filterContext) {
if (filterContext.Exception != null) {
// do your thing here.
}
}
}
Then you can put [WatchException]
on a Controller or Action Method, and it will let log exceptions. If you have a lot of Controllers, that might be tedious, so if you have a common Base Controller you can override OnActionExecuted
there and do the same thing. I prefer the filter method.
As far as what page to display, you'll need to create a customErrors section in your web.config and set it up for whatever status codes you want to handle.
Example:
<customErrors defaultRedirect="GenericError.htm" mode="RemoteOnly">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
As far as logging exceptions, I would recommend using ELMAH. It integrates nicely with ASP.NET MVC sites.