Content Negotiation with Nancy

I am doing some experiments with the Nancy and let me say that it looks pretty neat so far. This is an experiment about content negotiation.

Content negotiation is defined in wikipedia as:

Content negotiation is a mechanism defined in the HTTP specification that makes it possible to serve different versions of a document (or more generally, a resource) at the same URI, so that user agents can specify which version fit their capabilities the best.

This is something that will be supported in Nancy in future versions automatically. And even you will be able to override the behavior.

So far you can do something like:

public class SampleModule : NancyModule
{
    public SampleModule()
    {
        Get["example", c => c.Request.Accept("application/xml")] =
            a => Response.AsXml("hello xml");

        Get["example", c => c.Request.Accept("application/json")] =
            a => Response.AsJson("hello json");
    }
}

The Accept method is an extension method as follows:

public static class RequestHelper
{
    public static bool Accept(this Request request, string contentType)
    {
        return request.Headers.ContainsKey("Accept") 
            && request.Headers["Accept"]
                        .Any(c => c.Contains(contentType));
    }
}

This might seem an overhead for simple cases like Xml/Json but it opens the door for cases like rest versioning. I took this example from my friend (and now coworker) Pablo Cibraro.

For this example we have two different media types:

public static class MediaTypes
{
  public const string Version1 
        = "application/vnd.mycompany.myapp+xml";

  public const string Version2 
        = "application/vnd.mycompany.myapp-v2+xml";
}

And then we need to respond with two different representations of our Customer resource for each media type. One of them has address and the other one doesnt:

public class SampleModule : NancyModule
{
    public SampleModule()
    {
        Get["customer/{id}", c => c.Request.Accept(MediaTypes.Version1)] =
            a => Response.AsXml(new Customer{ Name = "Sideshow Bob" });

        Get["customer/{id}", c => c.Request.Accept(MediaTypes.Version2)] =
            a => Response.AsJson(new CustomerV2
                                      { 
                                        Name = "Sideshow Bob" 
                                        Addresses = { {"State Prison"} }
                                      });
    }
}

This show some of the power of Nancy:

  • The delegate to select the handler is separated from the handler itself.
  • Two handler for the same routes.

You can refactor this in two separated methods.

In contrasts the new WCF Web Apis (current version of Jan-2011) has a very useful processors pipelines but you have to handle the Route + VERB in the same method.


blog comments powered by Disqus
  • Categories

  • Archives