Home

Castle Stronghold

Rescues

A rescue is an association of a special view that will only be rendered if an exception happens. The view file must be present in a rescues folder directly under your views folder.

A rescue can be associated with a controller or per action. You can also bind a rescue with an exception type. If the action throws an exception (the action cannot swallow the exception), MonoRail will match the rescue definition that is closely related to the exception type and use the specified view.

To create an association you must use the RescueAttribute. For example:


using Castle.MonoRail.Framework;

[Rescue("dberror", typeof(System.Data.SqlException))]
public class ProductController : Controller
{
    [Rescue("commonerror")]
    public void Index()
    {
    throw new System.Data.SqlException("fake error");
    }

    [Rescue("dumbprogrammer", typeof(DivideByZeroException))]
    public void List()
    {
    int val = 0;
    int x = 10 / val;
    }

    public void Search()
    {
    }
}
            

The usage of the RescueAttribute in the example above defines the following rules:

Whenever an exception happens, the MonoRail context (which is per request) will populate the property LastException so your view can show the exception details.

Advanced usages

Sometimes it is necessary to execute code within a rescue, a simple view is not enough (usually the case when you want to do error reporting or logging). MonoRail therefore allows you to specify a controller that is used to execute the rescue and that handles the view rendering.

A rescue controller can be specified by using the RescueAttribute


using Castle.MonoRail.Framework;

[Rescue(typeof(RescueController), "RescueMethod")]
public class DemoController
{

}
            

The first argument tells MonoRail what controller class to use and the second is the name of the rescue method to call. The controller must inherit from SmartDispatcherController and the method to call has to have the following signature:


public void RescueMethod(Exception exception, IController controller, IControllerContext controllerContext)
            

This way you can call different rescue methods for different exceptions on one controller.

Here an example of multiple rescue methods and how they can be used by your controller:


[Layout("default")]
public class RescueController : SmartDispatcherController
{
    public void GenericError(Exception exception, IController controller, IControllerContext controllerContext)
    {

    }
    public void NotAuthorized(Exception exception, IController controller, IControllerContext controllerContext)
    {

    }
    public void WcfError(Exception exception, IController controller, IControllerContext controllerContext)
    {

    }
}
            

A controller can define different rescue methods for different types of exceptions:


public class DemoController
{
    [Rescue(typeof(RescueController), "NotAuthorized", typeof(FaultException<OperationPermissionFault>))]
    [Rescue(typeof(RescueController), "Timeout", typeof(TimeoutException))]
    [Rescue(typeof(RescueController), "GenericError", typeof(Exception))]
    public void List()
    {

    }
}
            

The rescue method signature is also defined in the IRescueController interface that can be implemented if only one rescue method needs to be present on the controller. If your rescue controller implements IRescueController you don't need to explicitly define what rescue method to use. MonoRail will default to Rescue(..)

A rescue pointing to a IRescueController would look like this:


[Rescue(typeof(RescueController))]
public void List()
{

}
            
Google
Search WWW Search castleproject.org