Introduction
The code attached to this article handles the creation of a web feed; either in the format of RSS 2.0 or Atom syndication. In this article, I will explain how to use the code.
Background
A web feed is a syndication of content, that allows internet users to subscribe to the content and receive notification about new additions, or easily retrieve and remix the content which is provided in a common format.
A web feed can include files, e.g., video, sound, images, or PDF documents. Some feed readers/aggregators are able to handle the playback of sound and video. In iTunes, it is possible to subscribe to podcasts and retrieve new episodes automatically, e.g., new radio programs or TV shows in a series.
I set out to create a common class to handle the syndication of content. Along the way, I learned more about the standards RSS and Atom, and the requirements to make iTunes accept and successfully subscribe to a web feed. I tested the resulting feeds in an online validation tool here.
Using the Code
The code is written in C#, and consists of the four classes Feed
, FeedItem
, FeedEmailAddress
, and FeedItemEnclosure
.
The Feed
class contains the main info about the feed, and a list of feed items. The FeedItem
class represents a feed item that might also hold an enclosed file. The FeedItemEnclosure
class represents the enclosed file itself, and the FeedEmailAddress
class contains info about a person (name and email address).
The Feed
class contains two methods, WriteRSS
and WriteAtom
, that create and write the web feeds in a given HttpContext
.
These classes can be used in an ASP.NET website as described in the following section. Using Visual Studio, a website can be created by choosing File / New / Web Site. Alternatively, the demo website in the attached demo package contains it all.
Preparing the website
- In the website, create the folder App_Code, if it does not already exist.
- From the source package attached with this article, add the four *.cs-files with the four classes
Feed
, FeedItem
, FeedEmailAddress
, and FeedItemEnclosure
to the App_Code folder.
- Create a new web form, or a new generic handler. (Do so in Visual Studio by going to Solution Explorer and right clicking the website and choosing Add New Item. Then, choose either to create a web form (ASPX), or a generic handler (ASHX).)
- In a web form, add the following code to the
Page_Load
event handler. In a generic handler, add the following code to the ProcessRequest
method.
Using the feed classes
- In the
Page_Load
event handler of a web form (ASPX), or in the ProcessRequest
method of a generic handler (ASHX), create an instance of the Feed
class with the values for the required parameters title
and description
:
Feed feed = new Feed("Northwind Employees", "Employees in the Northwind database");
- Then, I need some content to syndicate. It could be any list of content, e.g., a
DataTable
or a generic list of business objects. In this example, I use data from a SQL Server database, the Nortwhind database, and read all rows from the Employees table, as follows:
string connectionString =
@"Data Source=.\SqlExpress;Initial Catalog=Northwind;Integrated Security=True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(@"
SELECT LastName, FirstName, Title, TitleOfCourtesy, HireDate, Notes
FROM Employees
ORDER BY HireDate DESC, LastName ASC"
, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
}
}
connection.Close();
}
}
Inside the inner loop above, I create and add each feed item, see steps 3-6 below.
- The feed item in this example is generated from the current row in the
SqlDataReader
. First, I format the data for the title of the feed item so it will be like: Ms. Anne Dodsworth, Sales Representative:
string title = string.Format("{0} {1} {2}, {3}",
reader["TitleOfCourtesy"], reader["FirstName"],
reader["LastName"], reader["Title"]);
- Then, I create the feed item with the required
title
, and also provide the additional Description
and PublishDate
.
FeedItem feedItem = new FeedItem(title)
{
Description = (string)reader["Notes"],
PublishDate = (DateTime)reader["HireDate"]
};
- If a file should be enclosed with the feed item, I attach it with a URL to the file, the MIME type of the file, and the size in bytes, as follows:
string urlToFile = "http://nothing.nowhere/avatar.jpg";
string mimeType = "image/jpeg";
int sizeInBytes = 30000;
feedItem.Enclosure = new FeedItemEnclosure(urlToFile, mimeType, sizeInBytes);
- Now, I have completed the feed item, and will add it to the feed:
feed.Items.Add(feedItem);
- After looping through data, I'm ready to write the web feed to the current
HttpContext
. I choose to first create an RSS feed.
For the web form (ASPX), the current HttpContext
is the Context
property of the Page
:
feed.WriteRSS(this.Context);
For the generic handler (ASHX), the current HttpContext
is the context
parameter of the ProcessRequest
method:
feed.WriteRSS(context);
The generated RSS feed has the following XML content:
="1.0" ="utf-8"
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:media="http://search.yahoo.com/mrss/"
xml:lang="" version="2.0">
<channel>
<title>Northwind Employees</title>
<link>http://localhost:51529/FeedDemoWebSite/default.aspx</link>
<description>Employees in the Northwind database</description>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="self"
href="http://localhost:51529/FeedDemoWebSite/default.aspx"
type="application/rss+xml" />
<ttl>60</ttl>
<docs>http://cyber.law.harvard.edu/rss/rss.html</docs>
<pubDate>Sun, 26 Oct 2008 16:36:31 GMT</pubDate>
<lastBuildDate>Sun, 26 Oct 2008 16:36:31 GMT</lastBuildDate>
<itunes:explicit>no</itunes:explicit>
<itunes:subtitle>Employees in the Northwind database</itunes:subtitle>
<itunes:summary>Employees in the Northwind database</itunes:summary>
<item>
<title>Ms. Anne Dodsworth, Sales Representative</title>
<description>
Anne has a BA degree in English from St. Lawrence College.
She is fluent in French and German.
</description>
<pubDate>Tue, 15 Nov 1994 00:00:00 GMT</pubDate>
<enclosure url="http://nothing.nowhere/avatar.jpg"
type="image/jpeg" length="30000" />
<itunes:subtitle>
Anne has a BA degree in English from St. Lawrence College.
She is fluent in French and German.
</itunes:subtitle>
<itunes:summary>
Anne has a BA degree in English from St. Lawrence College.
She is fluent in French and German.
</itunes:summary>
<media:content url="http://nothing.nowhere/avatar.jpg"
fileSize="30000" type="image/jpeg" />
</item>
<item>
...
</item>
</channel>
</rss>
- Then, to create an Atom feed instead, I write:
feed.WriteAtom(this.Context)
The generated Atom feed has the following XML content:
="1.0" ="utf-8"
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="html">Northwind Employees</title>
<link rel="self" type="application/atom+xml"
href="http://localhost:51529/FeedDemoWebSite/default.aspx" />
<subtitle type="html">Employees in the Northwind database</subtitle>
<id>http://localhost:51529/FeedDemoWebSite/default.aspx</id>
<updated>2008-10-26T16:40:42.5191442Z</updated>
<entry>
<title>Ms. Anne Dodsworth, Sales Representative</title>
<updated>1994-11-15T00:00:00Z</updated>
<content type="html">
Anne has a BA degree in English from St. Lawrence College.
She is fluent in French and German.
</content>
<link rel="enclosure" type="image/jpeg"
length="30000" href="http://nothing.nowhere/avatar.jpg" />
</entry>
<entry>
...
</entry>
</feed>
- That's it. I have a feed (RSS or Atom) that users of my website can subscribe to:
The code in the classes
The source code is commented, and I hope that the comments will provide some answers to questions that may arise there. Therefore, I chose not to go into details with the classes here.
If you look at the code in the classes, I will be happy to hear about errors, improvements, suggestions, or other comments. I included some TODO
comments as well that indicate points I might change in the future.
Points of Interest
Note that to create a podcast that users can subscribe to from iTunes, enclose a file that iTunes supports, and provide the correct MIME type, e.g., "video/mp4" or "audio/mp3". For a list of MIME types for iTunes, see the section "iTunes RSS Tags" on Apple's page about iTunes podcasts.
History
- 26-10-2008 - Original article.