I’ve always been a fan of how Twitter organized their API. Particulary, I enjoyed being able to change the format of the response by just changing the extension of the URL from JSON to XML. A typical Twitter API call looks like this:
So while this public timeline call will return XML:
This one would return JSON:
The proper REST way to do this is by changing the headers in your request to ask for a particular file format. Indeed, an implementation utilizing request headers has already been written. However, I prefer Twitter’s implementation which coincidentally seems to be a feature of the Scala / Lift framework. To accomplish this with ASP.NET MVC, we are going to build an attribute that checks the incoming request and then attempts to render the resulting model in the selected format.
First, some words of caution. I don’t think this method will scale if your API / web application takes off. Although it is a great example of the DRY (don’t repeat yourself), code-once software development practice, it does somewhat tightly couple your API to your front end. Twitter faced a similar situation when their API was hosted on the same domain as the web application. Eventually, Twitter moved the API to api.twitter.com. This practice allows the API to evolve independently of the front-end of your application. With that warning in mind, let’s dive into the code.
They way we’ll implement this functionaly is to develop a custom action attribute which will check for a “format” parameter on each request to decide whether to return the model as a JSON, XML or the default view that the controller will return. This is slightly different from Twitter’s implementation but it simplifies some of the routing issues we would have with ASP.NET MVC. Using an API-driven development approach, I’ll start with an existing controller and add a (non-existent). This gives me an idea of how it would work.
I could add some additional parameters at this point to restrict which formats to accept, but we’ll leave that out for now (KISS – Keep It Simple Stupid!). Next we’ll just generate the class using the smart tag in Visual Studio which will create the stub for it. We want this action filter to execute before the response is returned to the client but after the data model has been populated. This implies we’ll be overriding the OnActionExecuted method:
At this point, everything should build. Our next step is to create two custom ActionResult subclasses which will return either Xml or Json representations of the model you pass in.
ASP.NET MVC includes a JsonResult which we’ll use for the JSON format. Although there is no XML equivalent, the MVCContrib library does have an XmlResult class. You can download the bits here to provide the XmlResult class (along with some other very useful features). Add the assembly as a reference to your project.
Now we have the two ActionResult’s we need to implement the solution. Below is a screenshot of the finished method. Essentially, we’re looking into the filter context to find the file extension. Depending on if it’s json or xml, we use a different action result serialization technique.
Notice that we need to set the JsonRequestBehavior in order for this to work. There are several security vulnerabilities which you should explore before defaulting this behavior at such a broad level. Phil Haack details some of the issues with JSON Hijacking here.
That’s all there is to it. Hope this helps!