Error Handling with the RescueAttribute
A
Rescue attribute can be used to specify a view that should be rendered when an exception occurs.
using System;
using MvcContrib.Filters;
[Rescue("DefaultError")]
public class HomeController : Controller
{
public ActionResult Index()
{
throw new Exception("Error");
}
}
In the above example, visiting mysite.com/Home/Index will throw an exception. However, because a RescueAttribute is specified a view called "DefaultError" will be rendered instead of the standard ASP.NET error page.
The ConventionController will always look for rescues in the folder
<project path>\Views\Shared\Rescues. With the above example, the path to the view would be
Views\Shared\Rescues\DefaultError.aspx.
A simple rescue view might look something like this:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<html>
<head><title>An error has occurred!</title></head>
<body>
Whoops! An error has occurred!
</body>
</html>
Rescues per Action
Recues do not have to be defined at the controller level, but can instead be defined for individual actions. This allows you to render a different error page depending on which action the exception occurs in.
using System;
using MvcContrib.Filters;
public class HomeController : Controller
{
[Rescue("IndexError")]
public ActionResult Index()
{
throw new Exception("Error");
}
[Rescue("AboutError")]
public ActionResult About()
{
throw new Exception("Error");
}
public ActionResult YellowScreenOfDeath()
{
throw new Exception("Error");
}
}
In the above example visiting mysite.com/Home/Index will cause the view Views\Rescues\IndexError.aspx to be rendered.
Visiting mysite.com/Home/About will cause the view Views\Rescues\AboutError.aspx to be rendered.
Visiting mysite.com/Home/YellowScreenOfDeath will result in the standard ASP.NET error page as no rescue was defined.
Specifying the Exception Types
Rescues can be limited to a particular exception type.
using System;
using MvcContrib;
using MvcContrib.Filters;
[Rescue("DefaultError", typeof(InvalidOperationException))]
public class HomeController : Controller
{
public ActionResult Index()
{
throw new InvalidOperationException("Error");
}
public ActionResult About()
{
throw new Exception("Error");
}
}
In the above example, visiting mysite.com/Home/Index will cause the DefaultError rescue to be rendered. However, visiting mysite.com/Home/About will result in the standard ASP.NET error page as the About action throws an exception of type System.Exception but the rescue is configured to only handle exceptions of type System.InvalidOperationException.
Automatic Location of Rescue Views
TODO
Accessing the Exception in the View
When a rescue view is rendered, the Exception is placed in the ViewData. This means that you can display information about the exception in the view. In order for this to work, your rescue view should inherit from
ViewPage<Exception>.
The view would look something like this:
<%@ Page Language="C#" Inherits="SampleMvc.ErrorPage" %>
<html>
<head><title>An error has occurred</title></head>
<body>
The following error has occurred: <%= ViewData.Model.Message %>
</body>
</html>
And the codebehind:
namespace SampleMvc
{
using System;
using System.Web.Mvc;
public class ErrorPage : ViewPage<Exception>
{
}
}
If you don't like to have CodeBehind files with your views, you can use the CLR syntax for generics to specify the correct base type in the Inherits attribute:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage`1[[System.Exception, mscorlib]]" %>
<html>
<head><title>An error has occurred</title></head>
<body>
The following error has occurred: <%= ViewData.Model.Message %>
</body>
</html>