Virtually every website that produces new content on a regular or semi-regular basis provides a syndication feed. Syndication feeds were first used with blogs as a
means for sharing the most recent entries, but soon spread to news sites. For instance, CNN.com has a feed that syndicates their breaking news headlines and one that
syndicates the latest sports news, along with many others. Today, syndication feeds are used to share all sort of content: Flickr syndicates each user's most recently
uploaded images; each project in CodePlex (Microsoft's open-source project hosting website) has a feed that syndicates the latest releases; and Twitter syndicates each
user's most recent tweets.
A syndication feed contains information about the most recently published items using a standardized XML format. Because the
syndication feed conforms to a known XML standard, its data can be parsed by any computer program that knows how to work with the syndication standard. For example,
you can subscribe to various syndication feeds using Microsoft Outlook's RSS Feeds folder. Adding a feed to this folder displays the syndication feed's content items;
furthermore, Outlook automatically checks the syndication feed every so often to determine if there is new content. Syndication feeds are also routinely consumed by other
websites. The ASP.NET Forums includes a feed that syndicates the 25 most recent posts. This feed is consumed and
displayed in the ASP.NET Developer Center on Microsoft's MSDN website. Similarly, you
could consume the Twitter feed that syndicates your latest tweets and display them on your blog.
Creating and consuming syndication feeds from an ASP.NET
application is a walk in the park thanks to the classes in the System.ServiceModel.Syndication namespace. This article shows how to use
these classes to create a syndication feed for your website as well as how to use them to consume and display syndication feeds from other websites. These techniques are
demonstrated in a demo web application, which is a website for a fictional book company, Nile.com. This demo site includes a feed that syndicates the most recently
published book titles; it also consumes and displays the headlines syndicated by RareBookNews.com.
A Bit of History
Before we delve into the meat of this article it would be worthwhile to spend a moment reviewing the history of syndication standards and the support for working with
syndication feeds in .NET. The first syndication feed standard was proposed by Dave Winer in 1997.
Over the years this initial syndication standard morphed into what is today known as RSS. The
RSS specification was frozen in 2003 with the release of RSS 2.0.
Shortly after RSS 2.0 was released, Sam Ruby proposed a new syndication format to address the shortcomings of the now frozen RSS standard. Over the
next several months Ruby and others created a new syndication format named Atom. The Atom 1.0
standard was ratified by the Internet Engineering Task Force (IETF) in 2007.
The .NET Framework did not provide
any built-in functionality for creating or consuming syndication feeds until version 3.5 with the introduction of the
namespace. The most germane class in this namespace is SyndicationFeed. As you can probably guess from its name, this
class represents a syndication feed. It has properties like
provide details about the feed. The content items that make up the feed are specified via the
Items property, which is a collection of SyndicationItem objects. The
class also has a static
Load method that parses and loads the information from a specified RSS 2.0 or Atom 1.0 syndication feed.
In addition to the
SyndicationItem classes, the
System.ServiceModel.Syndication namespace also includes two
formatter classes, Atom10FeedFormatter
and Rss20FeedFormatter. These classes
SyndicationFeed object and generate the corresponding XML content that conforms to either the Atom 1.0 or RSS 2.0 specificiations.
In 2000 a group at O'Reilly created their own syndication format standard that differed from the then current RSS 0.91 standard. Unfortunately,
this group named their new syndication format RSS 1.0, even though it was not related to RSS 0.91 (which later became RSS 2.0). Therefore, RSS 2.0 and RSS 1.0 are
significantly different from one another. Similarly, a number of sites started using Atom before it was standardized by the IETF, most notably Google. As a result, many of
Google's Atom syndication feeds still use Atom 0.3 instead of Atom 1.0.
SyndicationFeed class can only parse feeds that conform to the RSS
2.0 or Atom 1.0 standards. The good news is that the vast majority of the syndication feeds on the web use one of these two standards. And if you need to parse an RSS 1.0
or Atom 0.3 feed you can translate the XML content into Atom 1.0-compliant XML on the fly before loading it into a
SyndicationFeed object. For more
information on this technique check out Daniel Cazzulino's blog entry on upgrading Atom 0.3 feeds on the fly.
Creating a Syndication Feed For Your Website
Every website that routinely publishes any kind of content should offer a syndication feed. A syndication feed can be a static XML file that gets created automatically
whenever new content is published or it can be a dynamic web page that gets the latest published items and emits the appropriate XML markup. The demo website uses the
Creating a syndication feed from a dynamic web page involves three steps:
- Create a page that generates the feed's content.
- Get the most recently published items to appear in the syndication feed.
- Generate and output the feed's XML markup.
Let's walk through each of these steps.
Creating the Syndication Feed Web Page
The syndication feed web page's output is generated programmatically using the classes in the
Therefore, when creating this page make sure you do not associate it with a master page; once the page has been created remove all of the content from the
page except for the
The demo website's syndication feed is implemented by the
Feed.aspx page. The
contents of the
.aspx page follow:
Note that in addition to the
@Page directive the
.aspx portion also includes an
@OutputCache directive. The
@OutputCache directive caches the content returned by the syndication feed for the specified
Duration - in this case, 60 seconds. In other
words, when the first user requests the syndication feed the XML output is cached. For the next 60 seconds, requests for the syndication feed return the XML output stored in
the cache rather than having it regenerated by the page. The
VaryByParam attribute indicates that the output caching engine should maintain a separate
cached output for each unique
Type value. As we'll see shortly, the
Feed.aspx page accepts an optional
parameter that indicates the syndication format used. Visiting
Feed.aspx?Type=Atom returns the syndicated content in
accordance with the Atom 1.0 standard, whereas visiting
Feed.aspx?Type=RSS returns XML that is in accordance with the RSS 2.0 standard.
more information on output caching check out my article, Output Caching in ASP.NET.
Retrieving the Most Recently Published Items
The demo application's underlying author and title information comes from the pubs database, which you'll find
App_Data folder, and uses LINQ to SQL as the Data Access
Layer. The LINQ to SQL classes are defined in the
Pubs.dbml file, which you'll find in the
event handler in
Feed.aspx starts with the following statement, which retrieves the books from the
Titles table ordered in reverse
chronological order of their publish date.
That was easy!
Generating the Syndication Feed's XML Output
The last step is to turn the most recently published items into the appropriate syndication feed XML markup. After the
dataItems variable is created (see
the above code snippet) the
Feed.aspx page defines a constant that specifies the maximum number of recently published items to include in the feed and
then determines whether to generate an RSS 2.0 or Atom 1.0 syndication feed. The value of the
Type querystring parameter dictates which syndication
standard is used.
Regardless of what syndication standard you use, the code for constructing the
SyndicationFeed object is (mostly) identical. There are a few
edge cases that we'll address momentarily. However, the final lines of code that render the
SyndicationFeed object into the appropriate XML markup differ
based on the syndication standard. Furthermore, the syndication feed should send back a different
Content-Type header depending on the syndication
application/atom+xml for Atom 1.0 feeds and
application/rss+xml for RSS 2.0 feeds.
We are now ready to create the SyndicationFeed object and set its properties. As you can see, there are a number of properties associated with the
syndication feed, such as:
There is one method used in the above code snippet that is not part of the .NET Framework, and that's
GetFullyQualifiedUrl (it is defined
further down in the code-behind class). This method accepts a relative URL like
~/Default.aspx and returns the fully qualified URL, like
The next step is to define the syndication feed's items. This is done by creating a
SyndicationItem objects that contains a
SyndicationItem instance for each item to appear in the feed. Once this
been constructed it can be assigned to the
foreach loop uses the
Take method to iterate through only the first
maxItemsInFeed number of books in
dataItems collection. In each iteration a
SyndicationItem object is created, its properties are set, and the object is added to
SyndicationItems created immediately before the start of the loop. Note that the
collection for each
SyndicationItems object contains a link to the
Titles.aspx page. Typically each content item has a unique URL, such as
http://www.example.com/titles/Life_Without_Fear, and those unique URLs would be
what you would link to. However, I did not add such a unique page for each book for this demo and therefore decided to have all content items link to the same
There are two checks I added here to ensure that the information added to the feed conforms the the syndication specification being used. At the top of the loop
you can see that I bypass adding the current book to the feed's collection of SyndicationItems if there are no authors for the book. This is because the Atom 1.0 specification
requires author information with each item. I could have alternatively added a "dummy" author value for such books, with a name and e-mail address of "Unknown" and
"firstname.lastname@example.org", for example. (No such check is needed when generating an RSS 2.0 feed as the author information is optional in the RSS 2.0 spec.) The second
check is at the end of the inner
foreach loop, which adds the author information to the current
SyndicationItem object. Because the RSS 2.0
specification allows no more than one author we must break out of this loop after the first iteration to ensure that multiple authors are not added.
The final step is to
generate the XML markup for the syndication feed and output it to the
Response stream. This is handled via an
XmlWriter object and either
Rss20FeedFormatter class, depending on whether you want to generate an Atom 1.0 or RSS 2.0
feedWriter sends its output to the
Next, either an
Rss20FeedFormatter class is instantiated and its
WriteTo method is called, which
emits the rendered markup to
feedWriter, which outputs it to the client.
That's it! We now have a fully functional syndication feed that can emit either
RSS 2.0 or Atom 1.0 XML. For example, visting
Feed.aspx?Type=RSS returns the following content:
Consuming a Syndication Feed
In addition to creating and rendering syndication feeds, the
SyndicationFeed class can also be populated from an existing syndication feed. With a few
lines of code you can build a
SyndicationFeed object from an RSS 2.0 or Atom 1.0 feed from another site and then display it in a web page. The
Default.aspx page in the demo application provides such functionality, pulling the recent headlines from the RareBookNews.com syndication feed, http://www.rarebooknews.com/index.xml. To load the contents of a syndication feed use the
class's Load method, passing in
XmlReader instance. Once the
SyndicationFeed has been loaded you can bind its
Items collection to a data Web
Default.aspx page includes a ListView control named
BookNewsList and the following code in the
As you can see, the
Items collection is cached for one hour. It's good netiquette to cache the
syndication feed rather than re-requesting it every single time someone visits this page. It's also important to load the
SyndicationFeed object in a
try...catch block so that you can gracefully recover if the RareBookNews.com site is down.
ItemTemplate emits the HTML returned by the
DisplayFeedItem method, which is defined in the
code-behind class. This method takes in a SyndicationItem object and generates the HTML for display. Specifically, it creates a hyperlink that points to the content items URL
and displays the title as text. It also shows the item's published date and description.
Figure 1 shows the Default.aspx page when viewed through a browser. The text circled in red were the latest news headlines from RareBookNews.com at the
time of writing.
Figure 1: The RareBookNews.com Headlines Are Displayed In Default.aspx
Syndication has quickly grown from a technology that was strictly the domain of blogs to one that is embraced by all sorts of websites that routinely publish content.
Creating RSS 2.0 or Atom 1.0 syndication feeds, or consuming them, can be accomplished using the classes in the
namespace. Use the
SyndicationItem classes for modeling syndication feeds and their items and the
Rss20FeedFormatter classes for rendering a
SyndicationFeed object into the appropriate XML
markup. Be sure to download the demo application. It shows how to create an ASP.NET page that emits either an RSS 2.0 or Atom 1.0 syndication feed, as well as how to
consume and display another site's syndication feed.
Scott Mitchell, author of eight ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Scott works as an independent consultant, trainer, ...
This author has published 16 articles on DotNetSlackers. View other articles or the complete profile here.
You might also be interested in the following related blog posts
Announcing Microsoft Ajax Library (Preview 6) and the Microsoft Ajax Minifier
Accessing Images On Flickr From An ASP.NET Website Using The Flickr.Net Library
Mixing Silverlight and MS ASP.NET AJAX 3.5 in the same web application.
Code Review Singleton Pattern Issues
Upcoming Talk: Content Syndication With ASP.NET 3.5 (San Diego ASP.NET SIG)
Improved type safety when dealing with generic types, generic methods and reflection
Silverlight Twitter Client with authentication
ASP.NET Membership Tip: Requiring New Users To Change Their Password When Logging On For The First Time
Issue 45 - Markit Modules Slideshow and PageEar, DNN Stuff's Module Rotator, Monitter4DNN and Open Web Studio Tutorials
Please login to rate or to leave a comment.