Syndicating and Consuming RSS 1.0 (RDF) Feeds in ASP.NET 3.5By Scott Mitchell
Websites that produce new content on a regular basis should include a syndication feed, which is a specially formatted XML file that includes a summary of the most recently published items. Virtually all blogs, news sites, and social media sites have a syndication feed, and 4Guys is no exception. The 4GuysFromRolla.com syndication feed contains the most recent articles. Syndication feeds are meant to be consumed by computers. Sites like Technorati parse the syndication feeds from blogs and use that data to determine the topic du jour. Also, syndication feeds are commonly used by websites to display the latest headlines from related sites. For example, an ASP.NET community website could consume the 4GuysFromRolla.com syndication feed to display the latest 4Guys headlines.
Until recently, there was no built-in support for creating or consuming syndication feeds in the .NET Framework. That changed with the release of the .NET Framework version
3.5, which included a new namespace:
This new namespace includes a handful of classes for working with syndication feeds. As aforementioned, syndication feeds are XML files, and for the syndication feed to be
of any use it must conform to one of the popular syndication feed standards. The two most popular syndication feed standards are
RSS 2.0 and Atom 1.0, and these are the standards
supported by the classes in the
System.ServiceModel.Syndication namespace. But there is a third format that, while not as popular as RSS 2.0 or Atom 1.0, is still
used. That standard is RSS 1.0.
The good news is that with a little bit of work we can create a class that works with the RSS 1.0 standard and have this class used by the syndication feed-related classes in the .NET Framework 3.5 can be. This article introduces a free library, skmFeedFormatters, which you can use in an ASP.NET 3.5 application to create and consume RSS 1.0 feeds. (This same concept could be applied to creating and parsing Atom 0.3 feeds, as well.) Read on to learn more!
A Brief History of Syndication Feed Standards
The idea of online syndication feeds was first proposed by Dave Winer back in 1997 as a way for exposing the content of his blog in a machine-readable format. Dave called his standard RSS for Really Simple Syndication. Over the years he continued fine tuning the standard until 2003, at which point the standard was frozen with the release of RSS 2.0. RSS 2.0 is a very popular syndication feed standard in large part because it is very simple and straightforward, making it easy to implement and parse. For example, the 4Guys syndication feed adheres to the RSS 2.0 standard.
Around the same time a group from Netscape set about crafting a syndication standard based on Resource Description Framework (RDF), a standard proposed by the W3C for representing information about resources on the web. To make things as confusing as possible, this new syndication feed standard was named RDF Site Summary, or RSS for short, resulting in two differing standards with the same acronym! Eventually, this work by Netscape (and later O'Reilly) became known as RSS 1.0 and Dave's standard as RSS 2.0, although sometimes the RSS 1.0 standard is referred to as RDF to help remove any ambiguity.
After the RSS 2.0 standard was frozen in 2003, Sam Ruby proposed a new standard to overcome RSS 2.0's shortcomings. This new standard was defined by the community and named Atom. The first major release was Atom 0.3. After some more changes, the final, standardized version was released as Atom 1.0. (Unfortunately, some sites still syndicate content using the Atom 0.3 standard.)
The two most widely used standards are RSS 2.0 and Atom 1.0. However, some sites still use RSS 1.0 or Atom 0.3. For example, the popular tech news and discussion site Slashdot.org syndicates its content using RSS 1.0.
Creating and Consuming Syndication Feeds in ASP.NET 3.5
The .NET Framework version 3.5 introduced a new namespace,
System.ServiceModel.Syndication, with a number of classes for creating and consuming syndication feeds. These classes are divided into two categories: classes that model a syndication feed and the items in a feed, and classes that are responsible for transforming the classes that model syndication feeds into the appropriate XML and vice-a-versa.
- Classes That Model Syndication Feeds and Items
SyndicationFeed- represents a syndication feed. Has properties like
Itemsproperty represents the collection of content items expressed in the feed.
SyndicationItem- represents a specific syndication feed item and includes properties like
Authors, and so on.
- Classes That Transform Syndication Feeds To/From XML
Rss20FeedFormatter- can take a
SyndicationFeedobject and turn it into XML that conforms to the RSS 2.0 specification. Also, can be used to consume a properly-formatted RSS 2.0 feed, turning the XML into a
SyndicationFeedobject with its properties set based on the data in the consumed XML.
Atom10FeedFormatter- same as the
Rss20FeedFormatter, but uses the Atom 1.0 standard.
A more formal approach, in my opinion, is to create your own feed formatter class. The
Atom10FeedFormatter classes in the
System.ServiceModel.Syndication namespace derive from the base class
SyndicationFeedFormatter. We can create our
own formatter class by extending this base class. For example, we could create an
Atom03FeedFormatter class and use it to turn a
SyndicationFeed object into conforming XML, or consume an Atom 0.3 XML feed and generate a corresponding
The download available for download at the end of this article includes a class named
Rss10FeedFormatter, which can be used to create and consume RSS 1.0 feeds.
The download also includes a demo website showing this class in action. The remainder of this article explores the
(You could take the concepts presented in this article to create an
Atom03FeedFormatter class, or a class to work with other, more esoteric feed formats, should
the need arise.)
|How Do You Create and Consume Syndication Feeds Using the New Classes in the .NET Framework Version 3.5?|
This article does not walk through using the |
For a detailed look at creating and consuming feeds using the classes in the
A Quick Overview of the RSS 1.0 Standard
Before we get started examining the code for the
Rss10FeedFormatterclass, let's first take a moment to explore the RSS 1.0 standard, which is available online at http://web.resource.org/rss/1.0/spec. Like an RSS 2.0 feed, an RSS 1.0 feed is designed to express information about recently published content items. In a nutshell, an RSS 1.0 feed starts with the XML element
<RDF>. Following that, a
<channel>element describes information about the feed, including the feed's title, description, a link, and so on. The
<channel>element also must contain an
<items>element that serves as a table of contents of sorts. The feed's items come after the
<channel>element and are each represented by an
<item>element has children elements that describe the item's title, link, and description.
RSS 1.0 is more complex than RSS 2.0 in part because RSS 1.0 includes XML namespaces. The root element (
<RDF>) must include two namespaces:
http://purl.org/rss/1.0/, and these must appear in the root element like so:
Note that the
rdf namespace prefix must be used with the root element name, as in:
rdf prefix is also used
in other elements in the document.
One feature that makes RSS 2.0 so simple is that there are no attributes, save for the
version attribute in the root
<rss> element. However, in an
RSS 1.0 document there are many elements with attributes. For example, each item must have an
rdf:about attribute that provides a URI that uniquely identifies the
item within the document. (Usually the link to the content item is used for this attribute value.) This
rdf:about attribute is referenced in the
"table of contents" in the
An example RSS 1.0 feed composed of three content items follows.
Creating a Syndication Feed Formatter Class
The syndication feed formatter classes in the
System.ServiceModel.Syndicationnamespace derive from the
SyndicationFeedFormatterand are responsible for turning a
SyndicationFeedobject into corresponding XML and parsing XML and generating a
SyndicationFeedFormatterclass has a
Feedproperty that holds the
SyndicationFeedobject being worked on by the formatter. The
SyndicationFeedFormatterclass defines four abstract methods, which are methods that the base class must override:
CanRead(XmlReader)- returns a Boolean value that indicates whether the formatter can parse the supplied feed.
ReadFrom(XmlReader)- parses the supplied
XmlReader, reading its contents into the
SyndicationFeedobject stored in the
WriteTo(XmlWriter)- writes the information stored by the
SyndicationFeedobject in the
Feedproperty to the passed-in
CreateFeedInstance()- creates and returns a new
ReadFrommethod is used to turn XML into a
SyndicationFeedobject, whereas the
WriteTomethod transforms a
SyndicationFeedobject into XML.
SyndicationFeedFormatter class also defines an abstract string property named
Version, which indicates the syndication feed standard version being used.
Rss10FeedFormatter returns the value "Rss20", for example.
To create a syndication feed formatter class, start by creating a class that derives from
SyndicationFeedFormatter. The following code shows the shell of the
Rss10FeedFormatter class In addition to the abstract methods and property, this shell also includes two constructors and two read-only properties. The
first constructor is the default constructor, while the second one accepts a
SyndicationFeed object as an input parameter and passes it to the base class's
constructor. This base constructor called by this latter constructor assigns the supplied
SyndicationFeed object to the base class's
The two read-only properties simply define the namespaces used by the RSS 1.0 specification.
Consuming RSS 1.0 XML
SyndicationFeedFormatterbase class defines two abstract methods for reading an XML document:
CanRead(XmlReader)method returns a Boolean value indicating whether the feed can be read. We can only read an RSS 1.0 feed if it starts with the expected root element, namely
<RDF>with the namespace
http://www.w3.org/1999/02/22-rdf-syntax-ns#. This is precisely what the
CanReadmethod checks for:
The real work occurs in the
ReadFrom(XmlReader) method, which is responsible for parsing through the XML documents and creating a corresponding
object populated with
SyndicationItem objects for each item defined in the feed. This code consumes the bulk of the
Rss10FeedFormatter class. An
abbreviated version is shown below. Specifically, the code illustrated here reads in the
channel elements and assigns the values in a
The above code reads to the
<channel> element and then loops through the children elements. If it finds a
<title> element it extracts
the value and assigns it to the
Title property. Likewise, if it finds a
<link> element it extracts its value,
creates a new
SyndicationLink object, and adds is to the
Links collection. Any element other than
<description> is skipped.
Note that the formatter does not do any validation on the RSS 1.0 feed it's reading. For example, according to the specification the
<description> elements are required. However, no error is raised if these elements are missing.
By the time the
ReadFrom method completes, the
Feed property has had its relevant properties assigned to the corresponding values from the XML.
The demo website included in the download at the end of this article includes a page to test consuming an RSS 1.0 feed (
~/ConsumeRSS10.aspx). Here, you can enter
the URL to an RSS 1.0 feed. The specified feed can be parsed using the following three lines of code:
After the last line of code executes, the
formatter.Feed property contains the
SyndicationFeed information. You can work with this data programmatically
or bind it to a data Web control, such as a GridView or ListView. (The
~/ConsumeRSS10.aspx page binds the results to a ListView.) The following screen shot shows
~/ConsumeRSS10.aspx page in action when parsing the Slashdot RSS 1.0 feed.
Syndicating RSS 1.0 XML
SyndicationFeedFormatterclass also includes facilities for generating the XML for an existing
SyndicationFeedobject, and does so through its
WriteTo(XmlWriter)method, which outputs the corresponding XML to the passed-in
XmlWriterinstance. This code for writing the XML is a bit lengthy, as you might imagine. For the sake of brevity, let's just look at the code that creates the starting
<channel>element and its first few children elements.
The following code writes out the root node with the required namespace definitions.
Next, we need to write out the
<channel> element and its children. I've omitted some of the code that determines the value to use for the
rdf:about attribute, as well as the
<link> element, for brevity.
Unlike the code that consumes a feed, the code that syndicates it performs various checks to ensure that a valid feed is generated. For example, if the
SyndicationFeed object being syndicated doesn't include a value for its
Title property then the feed is invalid because RSS 1.0 feeds
must include a
<title> child element within the
The demo website includes the ability to generate a syndication feed using either:
- Atom 1.0
- RSS 2.0
- RSS 1.0
Feed.aspxpage passing in the type through the querystring (either
Atom). For example, to generate the feed in conformance with the RSS 1.0 standard you would visit:
Feed.aspx?Type=Rss10. The code in the
Feed.aspxpage's code-behind class builds the
SyndicationFeedobject and its
Itemsbased on data from the
pubsdatabase. It then uses the appropriate formatter class based on the
Typequerystring parameter value. In the following code,
myFeedis a populated
SyndicationFeedobject. The feed formatter class used outputs the XML to the
Response.OutputStreamstream, which returns the markup to the requesting user agent.
The syndication feed-related classes in the .NET Framework version 3.5 make it a snap to create and consume RSS 2.0 and Atom 1.0 syndication feeds. If you need to create or consume feeds that use an alternative standard you can create a custom feed formatter class. This article showed how to create a formatter class for RSS 1.0 feeds. You are welcome to download and use this code in your web applications.