Tigraine

Daniel Hoelbling-Inzko talks about programming

Using ELMAH Error logging with Castle MonoRail Rescues

Posted by Daniel Hölbling on July 3, 2009

On my last project I made ELMAH (the ever awesome ASP.NET error logging framework) work with ASP.NET MVC by modifying the routing logic a bit. It was quite simple since ASP.NET MVC throws HttpExceptions around quite liberally and you are frequently presented with a YSOD that then gets logged by ELMAH.

Using MonoRail the general routine of setting up ELMAH still applies (even simpler), but it’s customary to have a general rescue view that informs the user when something went wrong. Since the rescue concept in MR basically swallows Exceptions and prevents them from reaching ELMAH we need to serve them to ELMAH through ErrorSignaling.

Defining a rescue in MonoRail according to the tutorials looks like this:

[Rescue("generalError")]
public class DemoController : SmartDispatcherController
{
    [Rescue("indexError")]
    public void Index()
    {
        throw new DivideByZeroException();
    }
}

The string passed to the RescueAttribute identifies the name of the view to load within your Views\rescues\ folder if an exception occurs. This is bad for us because we can’t execute any code to signal ELMAH on the way to the view and within the view.

This is where the RescueController overload for RescueAttribute comes into play. You can define a whole controller that will handle exceptions and we can execute code there before rendering a view. To do so we just need to implement IRescueController and inherit from SmartDispatcherController:

[Layout("default")]
public class RescueController : SmartDispatcherController, IRescueController
{
    public void Rescue(Exception exception, IController controller, IControllerContext controllerContext)
    {
        ErrorSignal.FromCurrentContext().Raise(exception);
        RenderSharedView(Path.Combine("rescues", "generalerror"));
    }
}

We can use this new controller by changing the Rescue attribute:

[Rescue(typeof(RescueController))]
public void Index()
{
    throw new DivideByZeroException();
}

Now in case you want to have multiple error-pages (like one general and one telling the user he did something wrong) you could also define multiple rescue methods inside your RescueController and call each of those when needed:

[Rescue(typeof(RescueController))]
public class DemoController : SmartDispatcherController
{
    [Rescue(typeof(RescueController), "IndexRescue")]
    public void Index()
    {
        throw new DivideByZeroException();
    }

    public void List()     {         throw new NotImplementedException();     } }

If an exception was to occur in List() it would get handled by the Rescue method inside your RescueController, if Index throws MR will try to call a method called IndexRescue. And both can be logged by ELMAH.

comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more