RSS & Atom MediaTypeFormatter for ASP.NET WebAPI

Today we are going to build a custom formatter for ASP.NET WebAPI, deriving from MediaTypeFormatter class. It will return our model (or collection of models) in RSS or Atom format.
The Formatter is supposed to react to requests sent with request headers “Accept: application/atom+xml” and “Accept: application/rss+xml”.

Let’s get going.

Update – September 2012

This post was originally written against Web API beta. Since then the RC and then RTM versions have been released. Below is the code updated for the RTM version (the “proper” Web API released on 15th August).

Starting off

We will start as always when dealing with WebAPI – by creating a new ASP.NET MVC 4 project, and choosing WebAPI template. Make sure you are using Visual Studio 11 beta, cause the source files included in this post are VS11.


Our model is looking like this:

For simplicity, we will skip the DB altogether in this exercise, and use the usual repository pattern. The interface is as follows:

And the repository class as follows. Note that in the constructor we instantiate two objects into the collection so that we have some data to work with. Also, we omitted the Remove() and Update() methods, as they are irrelevant for our today’s examples.


Our ApiController also isn’t going to be anything sophisticated. In fact, for the purposes of this exercise, we are only interested in Get() and Get(int id) methods.

Basically all the ApiController does is calls the UrlRepository methods to retrieve the specific object instances. Notice that the controller itself doesn’t worry about any serialization or formatting (instead, just returns normal models). This – our core activity for today – is handled elsewhere.

Setting up the MediaTypeFormatter

Now that we have all the building blocks of the sample web application in place, we can start with our MediaTypeFormatter. I will be deriving from the MediaTypeFormatter class, but you might as well derive your formatter from BufferedMediaTypeFormatter. The difference is that MediaTypeFormatter wraps the read/write methods in asynchrounous methods, while BufferedMediaTypeFormatter uses synchronous ones.

Let’s add a class SyndicationFeedFormatter.cs to our project, and inherit from MediaTypeFormatter.

We will be playing around with application/atom+xml and application/rss+xml MIME types, so we might as well put them in some reusable properties.

In the constructor, we need to tell the formatter that these are the MIME types it should look for in the headers of the request.

Next step is to tell the formatter which custom types (models) to process. To do that, we need to override CanWriteType() method of MediaTypeFormatter. In our case, we will support Url type and IEnumerable of Url. If you wish to support all types, you can always simply return true from this method.

One more override we need to include is OnWriteToStreamAsync(), in which we will tell the formatter how to write the response to the client. This is where we will build up the actual RSS or Atom structure out of our models.

In this method, we check if the type is one of our supported types, and we call the BuildSyndicationFeed() private method, which will do all the magic.

This is what happens in the method:
1. We create an instance of SyndicationFeed. This is going to be then returned as either Atom- or RSS-structured XML, depending on what the client originally requested via the Headers.
2. We check if the object passed from the OnWriteToStreamAsync() is either Url type or IEnumerable of Url. Depedning on that, we’d have to treat it differently.
2a. If it’s IEnumerable, we iterate through the IEnumerable and call BuildSyndicationItem() for each Url instance.
2b. If it’s just a single Url object, then we call that method just once.
3. BuildSyndicationItem(), into which we’ll look in a moment, returns a SyndicationItem object, which we add to the Items property of the SyndicationFeed instance created beforehand.
4. Using the XmlWriter, we write either RSS or Atom feed (depending on the Content Type requested by the client) to the Stream that is going to be flushed as the Response.

The last thing to look at is the BuildSyndiactionItem() method, which transforms our model (Url) into SyndicationItem object.

Hooking up the formatter to GlobalConfiguration

Finally, we need to add our formatter to GlobalConfiguration in the Global.asax. GlobalConfiguration.Configuration exposes a Formatters collection, which contains all formatters. To include ours there, we add the following line in the Application_Start():

Trying it out

In order to try this out, we’ll add a couple of jQuery $.ajax calls to the Index.cshtml. First let’s try the Atom feed for all items:

This produces the following output:

Now, let’s try RSS for all items:

Also working as expected:

What about Atom and RSS for single item?

First, Atom:

And RSS:

Summary and source code

As you see it’s quite easy to build your own media type formatters for your ApiControllers. In fact, Gunnar Peipman has written a terrific blog post on extending content negotiation in WebApi here.

In our case, we have created both RSS and Atom formats using one formatter, supporting both a single model and an IEnumerable of model. The only downside of this solution, is that the client needs to specifically ask for MIME application/atom+xml and application/rss+xml. Therefore it’s suitable for RSS/Atom calls made programmatically somewhere from the backend, but not for accessing the feed via the browser, or using the client that doesn’t pass the Content Type headers correctly. In the next post, I’ll show how to work around it, and use this custom formatter also in regular GET calls triggered from the browser or, for that matter, anywhere else.

In the meantime, as always:
– source code (VS11 beta project), ZIP, 6.5MB