Introduction
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 System.ServiceModel.Syndication
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 Title, Description, Links, and Copyright, which
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 SyndicationFeed
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
SyndicationFeed and SyndicationItem classes, the System.ServiceModel.Syndication namespace also includes two
formatter classes, Atom10FeedFormatter
and Rss20FeedFormatter. These classes
take a SyndicationFeed object and generate the corresponding XML content that conforms to either the Atom 1.0 or RSS 2.0 specificiations.
Note: 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.
The 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
latter method.
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 System.ServiceModel.Syndication namespace.
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.aspx
page except for the @Page directive.
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 Type querystring
parameter that indicates the syndication format used. Visiting Feed.aspx or 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.
For
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
in the 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 App_Code folder.
The Page_Load
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
format: 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: Title, Description, Links, Copyright, and Language, among
others.
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
http://www.example.com/Default.aspx.
The next step is to define the syndication feed's items. This is done by creating a List of
SyndicationItem objects that contains a SyndicationItem instance for each item to appear in the feed. Once this List has
been constructed it can be assigned to the SyndicationFeed object's Items property.
The foreach loop uses the Take method to iterate through only the first maxItemsInFeed number of books in
the dataItems collection. In each iteration a SyndicationItem object is created, its properties are set, and the object is added to
feedItems, the List of SyndicationItems created immediately before the start of the loop. Note that the Links
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/ShowBook.aspx?ID=34, or 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
URL.
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
"unknown@example.com", 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
the Atom10FeedFormatter or Rss20FeedFormatter class, depending on whether you want to generate an Atom 1.0 or RSS 2.0
feed.
The XmlWriter object feedWriter sends its output to the Response object's OutputStream.
Next, either an Atom10FeedFormatter or 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 SyndicationFeed
class's Load method, passing in
an XmlReader instance. Once the SyndicationFeed has been loaded you can bind its Items collection to a data Web
control.
The Default.aspx page includes a ListView control named BookNewsList and the following code in the Page_Load
event handler:
As you can see, the SyndicationFeed object's 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.
The BookNewsList ListView's
ItemTemplate emits the HTML returned by the DisplayFeedItem method, which is defined in the Default.aspx page's
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

Conclusion
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 System.ServiceModel.Syndication
namespace. Use the SyndicationFeed and SyndicationItem classes for modeling syndication feeds and their items and the
Atom10FeedFormatter and 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.
Happy Programming!
References
About Scott Mitchell
 |
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
ASP.NET Membership Tip: Requiring New Users To Change Their Password When Logging On For The First Time
read more
Announcing Microsoft Ajax Library (Preview 6) and the Microsoft Ajax Minifier
read more
Silverlight Twitter Client with authentication
read more
Accessing Images On Flickr From An ASP.NET Website Using The Flickr.Net Library
read more
SOLUTION: JSLint.VS Add-In Always Reports "No Errors" Even For Invalid JavaScript Files
read more
Mixing Silverlight and MS ASP.NET AJAX 3.5 in the same web application.
read more
Improved type safety when dealing with generic types, generic methods and reflection
read more
Improved type safety when dealing with generic types, generic methods and reflection
read more
Code Review Singleton Pattern Issues
read more
Upcoming Talk: Content Syndication With ASP.NET 3.5 (San Diego ASP.NET SIG)
read more
|
|
Please login to rate or to leave a comment.