Skip to content

Configuration How Tos

simonthorogood edited this page Feb 7, 2011 · 7 revisions

On this page you’ll find a number of examples of registering resources using the fluent root ResourceSpace.Has, specifying some basic representations and with corresponding handler examples. We’ll be concentrating on using codecs other than the WebFormsCodec, as this means we only have a resource registration and a handler (no view!) to write for each example.

Registering a Customers resource to a URI with an XmlDataContract representation

  ResourceSpace.Has.ResourcesOfType<Customers>()
      .AtUri("/customers")
      .HandledBy<CustomersHandler>()
      .AsXmlDataContract();

This registers a Customers collection type at the URI /customers and specifies that it’ll be handled by a CustomerHandler. Here’s a (partial) example handler which only handles the GETting of customers (and assumes some kind of available repository implementation):

  public class CustomersHandler
  {
      public Customers Get()
      {
            return CustomerRepository.GetAll();
      }
  }

Registering a Customer resource to a URI template with integer ID and an XmlDataContract representation

This example allows us to retrieve a representation for a specific customer using their ID. This example introduces the concept of URI Templates – anything you see in curly braces can be thought of as a parameter – which by convention will usually have the same name as a parameter in a handler method.

  ResourceSpace.Has.ResourcesOfType<Customer>()
      .AtUri("/customer/{id}")
      .HandledBy<CustomerHandler>()
      .AsXmlDataContract();

Example handler:

  public class CustomerHandler
  {
      public Customer GetById(int id)
      {
            return CustomerRepository.GetById(id);
      }
  }

Note that OpenRasta will select the GetById method automatically when it receives an HTTP Get request on the /customers/{id} URI. Any method starting with Get will be matched. For a fuller discussion of how methods are selected by convention, see Handler Method Selection.

Registering more than one URI against a resource type

Here we’ll extend our previous Customers example and add another means of accessing lists of customers by region. Our resource registration now looks like this:

  ResourceSpace.Has.ResourcesOfType<Customers>()
      .AtUri("/customers")
      .And.AtUri("/customers/region/{region}")
      .HandledBy<CustomersHandler>()
      .AsXmlDataContract();

Our handler will now be extended by one method and will look like this:

  public class CustomersHandler
  {
      public Customers Get()
      {
            return CustomerRepository.GetAll();
      }

      public Customers GetByRegion(string region)
      {
          return CustomerRepository.GetByRegionName(region);
      }
  }

Note that when we add more URIs that return resources of type Customers, we normally do so on the same resource registration we used previously. Occasionally we might want to serve Customers from a different handler. This is possible, but is not “usual” behaviour. ’’’Care must be taken not to register the same resource type with the same handler twice!‘’’ This will cause an exception when the application starts and the fluent configuration is executed.

Serving a JSON representation in addition to an XML representation for all resources of type Customer

We simply add another codec registration to our existing Customers resource registration. Joy of joys – ‘’our handler does not need to change’’. We just got JSON support for free!

  ResourceSpace.Has.ResourcesOfType<Customers>()
      .AtUri("/customers")
      .And.AtUri("/customers/byRegion/{region}")
      .HandledBy<CustomersHandler>()
      .AsXmlDataContract()
      .And.AsJsonDataContract();

Serving resources using .WithoutUri

WithoutUri is a special type of modifier for a resource declaration. It states that we sometimes serve resources which are not directly accessible from a URI. Why would we want to do this? In the case of errors, for example, you might want to define your own Error class – much like you’d define your own Exception classes – and serve the error as a resource when something went wrong with retrieving or updating a Customer. Let’s say, for example, we’d like to have a TicketedError class so that if a user gets an error he gets served a ticket number he can use when calling support:

  ResourceSpace.Has.ResourcesOfType<TicketedError>()
      .WithoutUri
      .AsXmlDataContract()
      .And.AsJsonDataContract();

Note that we haven’t declared a handler here either. Well, why declare one for something we’re not going to serve directly? We do, however, have multiple representations for it. Because it’s ’’’cool’’’. Let’s define our TicketedError class now:

  public class TicketedError
  {
      public int TicketNumber { get; set; }
      public string Message { get; set; }
  }

Now let’s modify the CustomerHandler to give us the error in some circumstance – let’s say when the customer can’t be found. This will depend on some implementation of TicketRepository.CreateTicketedError which, when given an exception, returns a new TicketedError instance with its TicketNumber filled in. Note that we have to alter our Customers-returning method to return an OperationResult:
  public class CustomerHandler
  {
      public OperationResult GetById(int id)
      {
          try
          {
              return new OperationResult.OK { ResponseResource = CustomerRepository.GetById(id) };
          }
          catch (NotFoundException ex)
          {
              return new OperationResult.NotFound 
              {
                  ResponseResource = TicketRepository.CreateTicketedError(ex);
              }
          }
      }
  }

From an exception handling perspective, this is definitely ’’’not’’’ the best way to deal with errors! However, it does show – without too much darting around different topics – why resources without URIs could be served, why we’re not bound to return what the handler normally returns, and how we do it.

Registering your own codec implementation

Assuming you’ve written your own codec for a format OpenRasta doesn’t support, you’ll need to tell OpenRasta via configuration that you’ll be using this codec to assist with dealing with a particular format. Let’s say you’ve written an RdfCodec to supply representations of resources in RDF format. We’ll add this representation to the two we’re already using from our previous examples:

  ResourceSpace.Has.ResourcesOfType<Customers>()
      .AtUri("/customers")
      .And.AtUri("/customers/byRegion/{region}")
      .HandledBy<CustomersHandler>()
      .AsXmlDataContract()
      .And.AsJsonDataContract()
      .And.TranscodedBy<RdfCodec>(null);

Note that the null part is configuration that the codec can choose not to use. Our imaginary RdfCodec doesn’t have any configuration, so we leave it null. We could pass in any object we like, though – the codec will get to use whatever configuration object we pass in.

Clone this wiki locally