Integrating Exceptioneer with OpenRasta

[NOTE: This post was created using OpenRasta 2.0 RC (rev 429)]

One service I’ve found to be increasingly useful is Exceptioneer by Pixel Programming. As I’m about to start a new project using OpenRasta I wanted to be able to use Exceptioneer with it in order that I can log any exceptions effectively.

For a basic 404 error it was very easy. Just following the instructions on the Exceptioneer site for the ASP.NET integration worked a treat.

However, a little more work was required for when something like a Handler in OpenRasta threw an exception that didn’t get caught. In this case I had to set up an OperationInterceptor in order to catch the exception and send it to Exceptioneer.

Here is the ExceptionInterceptor class:

class ExceptionInterceptor : OperationInterceptor
{
    readonly IDependencyResolver resolver;

    public ExceptionInterceptor(IDependencyResolver resolver)
    {
        this.resolver = resolver;
    }

    public override Func<IEnumerable<OutputMember>> RewriteOperation
        (Func<IEnumerable<OutputMember>> operationBuilder)
    {
        return () =>
        {
            IEnumerable<OutputMember> result = null;
            try
            {
                result = operationBuilder();
            }
            catch (Exception ex)
            {
                Client exceptioneerClient = new Client();
                exceptioneerClient.CurrentException = ex;
                exceptioneerClient.Submit();
                throw;
            }
            return result;
        };
    }
}

Note that you have to include using Exceptioneer.WebClient; at the top of the file.

What this gives us is the ability to log any exception that is left uncaught from the Handler, log it then allow OpenRasta to continue on as it would have normally.

All that remains is to wire this up. In the Configuration class (if you’ve used the Visual Studio 2008 project template, or what ever your IConfigurationSource class is called otherwise) the following is added to the Configure method:

ResourceSpace.Uses.CustomDependency<IOperationInterceptor,
    ExceptionInterceptor>(DependencyLifetime.Transient);

 

Now any time a handler has an uncaught exception, it will be logged and sent off to Exceptioneer.

Further reading:

My First OpenRasta Project – Part 2 (Resource Templates)

To get started see part 1.

For this part the Invoice class has been expanded to include another property, you’ll see why in a moment. For now, it now looks like this:

public class Invoice
{
    public string Reference { get; set; }
    public DateTime Date { get; set; }
}

Up to this point we are just showing some simple XML based on one of the built in codecs that ship as part of OpenRasta. There is a single URI and it always returns the same thing. So far there is nothing much going on.

You can keep on adding resources to the ResourceSpace when you are configuring the site, but that is hardly a scalable solution when so many applications are based on dynamic data. You need a way to define a resource template.

The way this is done is by adding place holders into the URI. These placeholders are defined by a set of curly braces with a parameter name inside. This is a bit like the string.Format method, except you can use meaningful names instead of the ordinal position of the parameter.

The configuration of the ResourceSpace in the Configuration class is changed to:

ResourceSpace.Has.ResourcesOfType<Invoice>()
    .AtUri("/invoice/{reference}")
    .HandledBy<InvoiceHandler>()
    .AsXmlDataContract();

As you can see the only difference is that the parameter on the AtUri method is changed.

OpenRasta will then look in the handler for a method that matches the HTTP verb and the parameters defined in the template.

The InvoiceHandler now has a method that looks like this:

public Invoice Get(string reference)
{
    Invoice result = InvoiceRepository.GetInvoiceByReference(reference);
    return result;
}

Don’t worry about the InvoiceRepository. It simply exists to get an Invoice object from somewhere. It could be from a database, in memory, a file or wherever.

We can now go to the uri /invoice/123-ABC and get the output:

<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://schemas.datacontract.org/2004/07/MyFirstOpenRastaProject.Resources">
  <Date>2009-09-30T00:00:00+01:00</Date>
  <Reference>123-ABC</Reference>
</Invoice>

However, that’s not the whole story. You can do some pretty neat things with resource templates.

For example, if the method parameter on the resource handler is a DateTime object you can build up the URI template using the property names in the DateTime object. The template parameters will then be mapped to the properties in the DateTime object.

First the configuration has to be updated:

ResourceSpace.Has.ResourcesOfType<Invoice>()
    .AtUri("/invoice/{reference}")
    .And.AtUri("/invoice/{day}/{month}/{year}")
    .HandledBy<InvoiceHandler>()
    .AsXmlDataContract();

There is only one additional line here and that is to add a URI with a template containing the day, month and year. It is still the same type of resource and the code hasn’t changed. All that is new is the URI template. If you were to attempt to create a brand new ResourceSpace for the Invoice resource you’d get an error that the resource type was already registered in the system.

The InvoiceHandler class will need an additional method to handle the new template. The new method looks like this:

public Invoice Get(DateTime date)
{
    Invoice result = InvoiceRepository.GetInvoiceByDate(date);
    return result;
}

The result for the URI /invoice/29/09/2009 looks like this

<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://schemas.datacontract.org/2004/07/MyFirstOpenRastaProject.Resources">
  <Date>2009-09-29T00:00:00</Date>
  <Reference>3e5a4e9e-3b46-4b09-a8f8-45010411501b</Reference>
</Invoice>

My First OpenRasta Project – Part 1

On the OpenRasta Wiki there are some instructions on getting your project up and running the manual way, should you so wish. One of the new features introduced at the last beta was a Visual Studio 2008 project template, which installs as part of the binary distribution.

Once installed you can create an OpenRasta project by going to the “Visual C#” Project Types and selecting OpenRasta ASP.NET Application (3.5) from the templates on the right of the dialog.

OpenRasta: New Project

Once the project is created you’ll see that it has set the project up, added the references to the assemblies that it needs and created an initial handler, resource and views.

OpenRasta: Solution Explorer

Before continuing further a little explanation of what each of these things are is in order.

A resource is a source of information. It is referenced via a URI. This blog post is a resource, an image is a resource, an invoice is a resource. However, a resource does not imply any particular kind of representation. In terms of OpenRasta a resource is simply an object

A handler is an object that manages the interaction of the resources. In MVC parlance it would be the “C” or controller.

A view is a regular ASP.NET page that can be rendered via the WebFormsCodec. It is not compulsory to implement any views at all if you don’t need ASP.NET.

A codec is the class responsible for encoding and decoding the representation of a resource. The built in codecs are WebForms, JSON and two types of XML.

First Code

When you get started you’ll need to configure OpenRasta. It needs to know the details of the resources you want to expose and the handlers that can deal with those resources. To do that OpenRasta looks for a class in your project that implements the IConfigurationSource interface.

If you have two or more classes that implement this interface then the first one that is found will be used. As the project template already contains a Configuration class already set up and ready to go there is nothing additional to do other than set the configuration.

In the example I’m going to show, we will be rendering an invoice. So the configuration needs to look like this:

public class Configuration : IConfigurationSource
{
    public void Configure()
    {
        using (OpenRastaConfiguration.Manual)
        {
            ResourceSpace.Has.ResourcesOfType<Invoice>()
                .AtUri("/invoice")
                .HandledBy<InvoiceHandler>()
                .AsXmlDataContract();
        }
    }
}

The configuration happens through a fluent interface. The ResourceSpace is the root object where you can define the resources in your application, what handles them and how they are represented. In this case this is going to be a fairly simple example. As it is a fluent interface it does seem to be fairly self explanatory.

The Invoice class is a simple POCO DTO that represents an invoice. POCO means Plain Old CLR Object and DTO is a Data Transfer Object. In this example the Invoice just looks like this:

public class Invoice
{
    public string Reference { get; set; }
}

The InvoiceHandler class is another POCO that happens to have methods on it that are picked up by the use of conventions. If you have a method named after an HTTP verb (like GET or POST) then OpenRasta will use it to handle that verb.

In this example we are just going to return a simple Invoice object. I don’t want to complicate the example with other things at the present, so it will, in fact, always return an invoice with the same Reference property value.

public class InvoiceHandler
{
    public Invoice Get()
    {
        return new Invoice
        {
            Reference = "123-456/ABC"
        };
    }
}

As the configuration specified that the XML Data Contract codec was to be used the invoice is rendered using that codec. The output looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns:i="http://www.w3.org/2001/XMLSchema-instance"          xmlns="http://schemas.datacontract.org/2004/07/MyFirstOpenRastaProject.Resources">
  <Reference>123-456/ABC
</Invoice>

Obviously at this stage it isn’t very useful. This is just a quick demonstration showing how quickly something can be set up. In coming parts I’ll be addressing other issues that so that more useful things can be done.

 

NOTE: This blog post is based on OpenRasta 2.0 Beta 2 (2.0.2069.364): [Download]

Technorati Tags: