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>

Last edited Jul 20, 2008 at 3:32 PM by JeremyS, version 2

Comments

sark3k Jan 6, 2011 at 4:11 PM 
Towards the top of the article, it states "The ConventionController will always look for rescues in the folder <project path>\Views\Shared\Rescues". Farther down, you see an example which will "cause the view Views\Rescues\IndexError.aspx to be rendered". The example is incorrect, after reviewing mvccontrib source and testing, the ONLY location valid for the rescues is the original stated convention of <project path>\Views\Shared\Rescues.

pupeno Jan 8, 2010 at 6:44 PM 
Can you set the http return code on it?