Although I left WCF Web API, I am very passionate about continuing on my journey toward understanding REST and how it fits with Web API. For that reason you will likely continue to see posts on REST and Web API here along with my new found love node.js.
If you head over to our codeplex site, one question commonly asked is “Does Web API support hypermedia?” To understand this question you have to first understand what hypermedia is. I am not going to cover that here, but there are many articles about it, a ton of discussions in the REST Discuss Yahoo group and a new book by Mike Amundsen which is well worth reading. (I need to write a review for the book at some point). I gave a quick primer which doesn’t do justice, but will get you through this post here.
The answer to the question depends on your notion of support:
- If by support you mean, “Can I embed links within my responses which will indicate to my client available resources / state transitions?” then the answer is YES.
- If it means, “Will Web API automatically embed links for related resources out of the box?” the answer is no”.
Web API was designed to be highly pluggable, especially as it relates to how a request is handled, or how the content is processed. You can take advantage of this for plugging in your own custom code for generating hypermedia.
In the rest of this post I will discuss various strategies for how as well as point you to several samples.
Why formatters are a good choice
There are several different ways you can technically attach hypermedia including formatters, message handlers, and operation handlers. Formatters are the way we would recommend as they are specifically responsible for taking the result of an operation (could be anything) and transforming it into some representation. That representation can contain hypermedia.
How conneg and formatters work in Web API
Each Web API host has a collection of formatters. Each formatter specifies information about the media types it supports. On any incoming request, if content is sent, Web API matches up the incoming request’s Content-Type against the available formatters to choose one to appropriately handle processing the content in the request. It invokes the matched formatter passing in the content of the request. The formatter then outputs a CLR object which is passed to the operation.
Once the operation has completed, Web API performs server side content-negotiation to determine the response representation. It looks at the accept header supplied by the client in the request and matches up against the available formatters. The algorithm will look for a best match based on the specified media type / media type ranges in the accept along with the q-values. Once a formatter is identified it will be invoked passing in the return value of the operation. The formatter takes the the incoming value and writes out the representation.
As the formatter is writing out the response, it can also embed hypermedia controls i.e. links and forms. If you read the REST in Practice book they show a media type “application/vnd-restbucks+xml” which contains hypermedia. You can create a custom RestBucksFormatter that handles that media type. If you check the RestBucks sample for Web API on codeplex, you’ll see an example of this.
Url / Link generation
In a hypermedia based system, links are generated based on a state machine. Depending on the state of the resource, different links apply. As soon as you start writing the formatter you will have to deal with how to handle the generation of links. There’s a several approaches you can use.
Generate links within the formatter.
With this method, your formatter contains the state machine logic for generating links. In the case of an Order management API, the API implementation for GET can return an order. The formatter then comes a long and grabs the order and adds appropriate links based on the state of the order. I used to be a big fan of this approach as it keeps links as separate concern from the API code itself. I’ve since changed that opinion, as I don’t view links as a separate concern
The upside of this approach is everything is nicely encapsulated within the formatter. The downside is that it makes it harder for one to follow the logic of the system if they are reading the API code. They must also read the formatter. It also means that the link code is duplicated if you support different variants like xml and json that require the hypermedia.
Example: Hypermedia formatter for contacts
A while ago, Mike Amundsen visited Microsoft and I was fortunate to have the chance to brainstorm with him around Media Type design. We took the ContactManager example and spiked on how it “could” look if it used hypermedia. The implementation used the approach I just described. Below is a snapshot of how the media type itself looks. The “.” for the uri is a placeholder as the uri doesn’t matter, it is opaque to the client.
One thing to note here if you are familiar with hypermedia, is that it is not using the standard link element with “rel” and “href” attributes that you are probably accustomed to seeing. Instead a domain specific format is used to to represent links and forms. In this example, Tweets has an href indicating where to go to get tweets. DM is a form for sending a direct message. The query named “query-search” includes a form with fields for specifying search criteria. This type of approach of using domain specific hypermedia deserves it’s own post. It has several advantages in that it is more intention revealing, offers richer semantics than just being limited to a rel and href , and also doesn’t abuse the rel tag.
You can find all the code for Mike’s example at his github repo here
Generate links close to the operation.
I mentioned above how my perspective changed on this. My current understanding is that links relate completely to the core business logic of the system as opposed to being a cross-cutting concern like logging. They are NOT a separate concern. Think of your Web API as a bridge between HTTP and your business domain, not the domain itself. Thus the model being returned from your API being tailored to HTTP is completely valid. This is not about DTOs.
With this approach links will get generated by the operation. Your operation returns a model that has links on it. The formatter’s responsibility is then to take the model and encode the links correctly within the representation. This allows you to add new formatters easily without replicating the linking logic. You could have an ILinkable<T> type which your formatter understands for attaching links. This type is not sufficient for collections as in that case you have links nested at multiple levels. For that you can have an ILinkableCollection<T> that contains items of ILinkable<T>. Thus you can return an ILinkableCollection<Order> that contains within ILinkable<Order> instances each with their own links attached.
The link generation code itself does not have to sit within the operation itself. Introduce a separate service such as IOrderLinkService which has that specific responsibility and have it injected via an IoC container. The service exposes an AddLinks method which accepts ILinkable<T> or an ILinkableCollection<T>. Although the link logic does not exist within the service, it is easy to step through the code to debug the logic.
Example: Domain specific media type for Orders
Here’s a snippet of the Order API.
The link service is injected into the API. The Get method then invokes it passing the order.
Once the service is called it looks at the state of the order and adds links appropriately. Above you can see that when the order is in the created state, a link is added for an approval resource.
The code can definitely be refactored / made cleaner, but it illustrates the basic idea. As an example of something more sophisticated, the RestBucks port for Web API contains a ResourceLinker service that generates links via accepting a lambda expression.
Lastly there is the formatter itself. It will take the linked order and write out the appropriate links. Below is a skeleton of such a formatter.
Example: HAL formatter
HAL is a media type in draft at IANA that is designed specifically for expressing resources and links. Steve Michelotti has created a formatter for HAL. The way it works is your operations return a HalResource model. HalResource can recursively contain other resources thus you can have a very deep resource map. You can use it both on the client and the server. The formatter then takes that model and writes it out appropriately as HAL, it also do the reverse taking a HAL response and turning it back into a HAL model. You can read more about how to use it in Steve’s post. Hopefully we’ll see this on nuget soon!
Example: XHTML using the plain old XML formatter
Mike Amundsen talks quite a bit about XHTML in his new book. What makes XHTML interesting from a hypermedia perspective is that it contains native support for hypermedia affordances, and browsers naturally understand it. You can express links very easily using an <a href=””> construct. You can embed forms as well as it supports them natively. It also offers annotations like name, id and style which we can use in order to attach domain specifics to the elements. For an rich example of what you can achieve with XHTML check Mike’s ALPS micro-blogging specification.
Web API supports the ability for you to return XML dom objects directly, for example you can return XmlDocument/XDocument instead of a model. The beauty of this is that you can easily represent any XHTML document using the XML dom. Thus in your operation you simply create an XmlDocument, populate it appropriately and return it. The formatter will very happily then write it out to XHTML.
Here’s a skeletal snippet illustrating what I mean
If you do use this approach one thing you will need to do is add the media type to the default XML formatter. You can do that off of the configuration object’s Formatters collection using code similar to the following:
Example: XHTML formatter example using Razor
Recently I delivered a talk at Tulsa TechFest where I demonstrated RestBugs. A sample app written by Howard Dierking. It contains a web API for bug tracking which and supports XHTML via a custom formatter. The app also includes a console hypermedia client which I hope to cover in another post. You can watch the video from that talk here. If you jump to the last 30 minutes that’s where I get into RestBugs where I cover the API, formatter and the hypermedia client.
One interesting thing about the app is the formatter that is used. Instead of manually writing out the XML, Howard uses a custom Razor formatter. The formatter looks for a custom content header which specifies the template. It then uses ASP.NET’s Razor engine to take the model passed in along with the template to generate the XHTML. To illustrate here is the template for the bug list.
I really like this approach because it gives you absolute freedom to format things exactly the way you want them without jumping through a 1000 hoops in code. I know from discussions with Mike that using templates is really his only way to fly.
You don’t have to wait for that future post I eluded to (which might never happen) to try the code in the talk as I’ve put it on Dropbox here. You’ll find RestBugs including the Razor formatter and the client.
Generate links through middleware.
This approach is more of a hybrid of the other two. Instead of generating links in the formatter or the operation, you use an operation handler. The operation handler takes the model that is returned like ILinkable<Order> and then adds the appropriate links.
Taking the above code, you can simply move the logic to an operation handler to achieve the same.
The pros of this is that it still allows the link logic to be used cross formatters, and it makes the code within your operation much tighter. The downside, and why I no longer prefer it is that it makes the code harder to follow. You have to know that a handler was registered which applies the links and you have to find that handler to understand the link logic.
How to generate the uris themselves
Aside from the strategy to embed links there is the question of how best to generate uris. Here’s a couple of recommendations on how you can do this.
If you can get away with relative uris do it. What I mean by that is this, let’s say you have a link to an Order approval resource for order 5. You can generate a link for “/order/approval/5”. The client will take the uri and append it to the host url in order to navigate. This alleviates the need for you having to get access to the base url for the site when you generate urls.
If you have multiple domains where your resources live, or if you want clients to always get the full uri so that they can simply copy/paste, use absolute uris.
For absolute uris, create a service which is configured with a map of all the available uris and exposes methods for retrieving them.
OrdersBaseUri returns “http://contoso.orders.com” the address of the order system, while InventoryBaseUri returns “http://constoso.inventory.com” for the inventory system. UspsBaseUri is a the address for a third party site for shipping .
The uri service can then get injected into the link uri service which can use it to generate absolute uris.
Your mileage may vary
As you can see from this post, there are many different ways to approach implementing a hypermedia system with WCF Web API. As building hypermedia systems for web apis is still a pretty young topic, I don’t think there’s a clear winner yet on which hypermedia design approach to use. By extension there is also no clear winner on implementation. Over time and with more people building hypermedia based systems, hopefully this will change and there will be more accepted standards.
What has worked for you? Do you have a particular approach you’d like to see better support for in the box?