Overview
Every other
website that routinely publishes contents provides syndication feed to its
users. 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 provides the appropriate XML markup. A
good example of data-sharing using XML is Web site syndication, commonly found
in news sites and Web logs. Another example is Twitter provides feeds of user's
most recent tweets.
With the
help of syndication feed, a Web site publishes its latest content in an
XML-formatted file. Because it conforms to a known XML standard, its data can
be parsed by any language that knows how to work with the syndication standard.
There are a number of syndication formats in use, one of the more popular ones
being RSS 2.0.
About Syndication in
.Net
Microsoft
introduced System.ServiceModel.Syndication namespace in .Net Framework 3.5,
before that there was not any built-in mechanism for creating or consuming the
Syndication feeds. We’ll use SyndicationFeed class of this namespace. This
class has a static Load method that parses and loads the information from a
specified RSS 2.0 or Atom 1.0 syndication feed. Beside that this class contains
various properties like Title, Description, Links, and Copyright etc. It
exposes collection of SyndicationItem objects as Items property which makes up
feeds.
With the
help of System.ServiceModel.Syndication namespace, creating or consuming
syndication feeds from an ASP.NET application is straight forward. In this article
we’ll see how to create syndication feed for your website by creating a
sample web application. We’ll create both RSS 2.0 and Atom 1.0 feed based on
QueryString parameter.
Creating a Syndication
Feed for Your Website
First of
all create an ASP.Net Empty Web Application and give it a name as “RssFeeder”.
Add a new
web page to this application and give it a name “Feed.aspx”.
Remove
all the HTML of the page except @Page directive and @OutputCache directive for caching of feed items,
now your aspx page should be look like:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Feed.aspx.cs"
Inherits="RssFeeder.Feed" %>
<%@ OutputCache Duration="60" VaryByParam="Type" %>
|
The @OutputCache directive caches the content
returned by the syndication feed for the specified Duration - in our case, 60
seconds. The VaryByParam attribute indicates that the output caching engine
should maintain a separate cached output for each unique Type value. Our
Feed.aspx page accepts an optional Type querystring parameter that indicates
the syndication format used. i.e., Atom 1.0(by selecting “/Feed.aspx” or “Feed.aspx?Type=Atom”)
or RSS 2.0(by selecting “/Feed.aspx?Type=RSS”).
Now add
two private properties (FeedType and NoOfFeeds) in our code-behind to capture
the value from QueryString parameter.
public string FeedType
{
get
{
return
Request.QueryString["type"];
}
}
public int NoOfFeeds
{
get
{
int number;
if
(Int32.TryParse(Request.QueryString["feedsCount"], out number))
{
return number;
}
//default return 10 items.
return 10;
}
}
|
Create
one proxy class, we’ll use this class to get feed items, in this case we’ll
create hard coded items but in real scenario feed contents will be populated
from DB or any other source.
public class FeedItemProxy
{
public string Title { get; set; }
public DateTime FeedDate { get; set; }
public string Summary { get; set; }
public string FeedUrl { get; set; }
public string AuthorName { get; set; }
public string AuthorEmail { get; set; }
}
|
We have
defined all the basic properties required for feed items. Now create one method
that’ll return list of FeedItemProxy
class based on the number of feed items required, if there is no value for feedsCount query
string parameter, it’ll select 10 as default number of feeds (see NoOfFeeds
property).
/// <summary>
/// Get Feed Items
/// </summary>
/// <returns></returns>
private List<FeedItemProxy>
GetFeedItems()
{
var feedItems = new List<FeedItemProxy>();
//Create items for selcted number of feeds.
var totalFeeds = NoOfFeeds;
for (var i = 1; i <= totalFeeds;
i++)
{
feedItems.Add(new FeedItemProxy
{
Title
= "Test Feed " + i,
FeedDate = DateTime.Now,
Summary = "<b>This is
summary of Test Feed " + i + "</b>",
FeedUrl = "http://www.google.co.in",
AuthorName = "TestAuthor" + i,
AuthorEmail = "testauthor" + i + "@test.com"
});
}
return feedItems;
}
|
Once our
feed data is ready, we’ll create one method and name it as “GenerateFeeds”,
this method will be called on Page Load event to create the syndication feeds.
We’ll see all code written inside this method step by step.
First of
all check if feeds requested for Atom 1.0 or RSS 2.0.
var isRssFeed = (!string.IsNullOrEmpty(FeedType)
&& FeedType.ToLower()
== "rss");
|
The
syndication feed send back a different Content-Type header depending on the selected
syndication format:
// set ContentType as per selected feed type.
Response.ContentType = isRssFeed
? "application/rss+xml"
: "application/atom+xml";
|
We
are now ready to create the SyndicationFeed object and set its properties. Add
reference to System.ServiceModel dll and add
System.ServiceModel.Syndication namespace.
var feed = new SyndicationFeed
{
Title = new TextSyndicationContent("Test Feeds"),
Language = "en-us",
LastUpdatedTime = DateTime.Now,
Copyright = new TextSyndicationContent("Copyright Test Feeder 2013"),
Description = new TextSyndicationContent("This is a Test Feed loaded from Feeder")
};
|
The
next step is to define the syndication feed's items. Create a List of
SyndicationItem objects that contains a SyndicationItem instance for each item
to appear in the feed. Once this List has been created assign this to the
SyndicationFeed object's Items property.
//Get proxy item list for feed.
var proxyItems = GetFeedItems();
var feedItems = new List<SyndicationItem>();
foreach (var proxyItem in proxyItems)
{
var item = new SyndicationItem
{
Title = SyndicationContent.CreatePlaintextContent(proxyItem.Title),
PublishDate = proxyItem.FeedDate,
Summary = SyndicationContent.CreateHtmlContent(proxyItem.Summary)
};
item.Links.Add(SyndicationLink.CreateAlternateLink(
new Uri(proxyItem.FeedUrl)));
var authInfo = new SyndicationPerson
{
Name =
proxyItem.AuthorName,
Email =
proxyItem.AuthorEmail
};
item.Authors.Add(authInfo);
// Add the item to the feed
feedItems.Add(item);
}
feed.Items = feedItems;
|
In
above code we created the feed items by iterating over proxy item list and then
assigned this feed item list to “Items” property.
Last
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 (for Atom
1.0) or Rss20FeedFormatter (for RSS
2.0) class. And in the end close the XmlWriter.
// Return the feed's XML content as the response
var feedWriter = XmlWriter.Create(Response.OutputStream);
if (isRssFeed)
{
// RSS 2.0
Rss20FeedFormatter
rssFormatter = new Rss20FeedFormatter(feed);
rssFormatter.WriteTo(feedWriter);
}
else
{
Atom10FeedFormatter
atomFormatter = new Atom10FeedFormatter(feed);
atomFormatter.WriteTo(feedWriter);
}
feedWriter.Close();
|
We
are done with creating syndication feed and we now have a fully functional
syndication feed that can return either RSS 2.0 or Atom 1.0 feed XML.
Output for RSS 2.0
Get
top 5 feed XML for RSS 2.0 by requesting to URL “~/Feed.aspx?type=rss&feedsCount=5”
and your XML will be look like:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title>Test
Feeds</title>
<description>This is a Test Feed loaded from Feeder</description>
<language>en-us</language>
<copyright>Copyright
Test Feeder 2013</copyright>
<lastBuildDate>Tue, 10 Sep 2013 19:07:59 +0530</lastBuildDate>
<item>
<link>http://www.google.co.in/</link>
<author>testauthor1@test.com</author>
<title>Test
Feed 1</title>
<description>
<b>This is summary of Test
Feed 1</b>
</description>
<pubDate>Tue,
10 Sep 2013 19:07:59 +0530</pubDate>
</item>
<item>
<link>http://www.google.co.in/</link>
<author>testauthor2@test.com</author>
<title>Test
Feed 2</title>
<description>
<b>This is summary of Test
Feed 2</b>
</description>
<pubDate>Tue,
10 Sep 2013 19:07:59 +0530</pubDate>
</item>
<item>
<link>http://www.google.co.in/</link>
<author>testauthor3@test.com</author>
<title>Test
Feed 3</title>
<description>
<b>This is summary of Test
Feed 3</b>
</description>
<pubDate>Tue,
10 Sep 2013 19:07:59 +0530</pubDate>
</item>
<item>
<link>http://www.google.co.in/</link>
<author>testauthor4@test.com</author>
<title>Test
Feed 4</title>
<description>
<b>This is summary of Test
Feed 4</b>
</description>
<pubDate>Tue,
10 Sep 2013 19:07:59 +0530</pubDate>
</item>
<item>
<link>http://www.google.co.in/</link>
<author>testauthor5@test.com</author>
<title>Test
Feed 5</title>
<description>
<b>This is summary of Test
Feed 5</b>
</description>
<pubDate>Tue,
10 Sep 2013 19:07:59 +0530</pubDate>
</item>
</channel>
</rss>
|
Output for Atom 1.0
Get
top 5 feed XML for Atom 1.0 by requesting to URL ~/Feed.aspx?type=atom&feedsCount=5”
or “~/Feed.aspx? feedsCount=5” and your XML will be look like:
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Test Feeds</title>
<subtitle type="text">This is a Test Feed loaded
from Feeder</subtitle>
<id>uuid:a9e7fbfc-9451-4b62-900f-b1d2093ead19;id=34</id>
<rights type="text">Copyright Test Feeder 2013</rights>
<updated>2013-09-10T19:34:02+05:30</updated>
<entry>
<id>uuid:a9e7fbfc-9451-4b62-900f-b1d2093ead19;id=35</id>
<title type="text">Test Feed 1</title>
<summary type="html"><b>This
is summary of Test Feed 1</b></summary>
<published>2013-09-10T19:34:02+05:30</published>
<updated>2013-09-10T14:04:02Z</updated>
<author>
<name>TestAuthor1</name>
<email>testauthor1@test.com</email>
</author>
<link rel="alternate" href="http://www.google.co.in/" />
</entry>
<entry>
<id>uuid:a9e7fbfc-9451-4b62-900f-b1d2093ead19;id=36</id>
<title type="text">Test Feed 2</title>
<summary type="html"><b>This
is summary of Test Feed 2</b></summary>
<published>2013-09-10T19:34:02+05:30</published>
<updated>2013-09-10T14:04:02Z</updated>
<author>
<name>TestAuthor2</name>
<email>testauthor2@test.com</email>
</author>
<link rel="alternate" href="http://www.google.co.in/" />
</entry>
<entry>
<id>uuid:a9e7fbfc-9451-4b62-900f-b1d2093ead19;id=37</id>
<title type="text">Test Feed 3</title>
<summary type="html"><b>This
is summary of Test Feed 3</b></summary>
<published>2013-09-10T19:34:02+05:30</published>
<updated>2013-09-10T14:04:02Z</updated>
<author>
<name>TestAuthor3</name>
<email>testauthor3@test.com</email>
</author>
<link rel="alternate" href="http://www.google.co.in/" />
</entry>
<entry>
<id>uuid:a9e7fbfc-9451-4b62-900f-b1d2093ead19;id=38</id>
<title type="text">Test Feed 4</title>
<summary type="html"><b>This
is summary of Test Feed 4</b></summary>
<published>2013-09-10T19:34:02+05:30</published>
<updated>2013-09-10T14:04:02Z</updated>
<author>
<name>TestAuthor4</name>
<email>testauthor4@test.com</email>
</author>
<link rel="alternate" href="http://www.google.co.in/" />
</entry>
<entry>
<id>uuid:a9e7fbfc-9451-4b62-900f-b1d2093ead19;id=39</id>
<title type="text">Test Feed 5</title>
<summary type="html"><b>This
is summary of Test Feed 5</b></summary>
<published>2013-09-10T19:34:02+05:30</published>
<updated>2013-09-10T14:04:02Z</updated>
<author>
<name>TestAuthor5</name>
<email>testauthor5@test.com</email>
</author>
<link rel="alternate" href="http://www.google.co.in/" />
</entry>
</feed>
|
Compare RSS 2.0 and Atom 1.0
Atom
Feed is similar to RSS Feed but it differ only in tags, One main difference is RSS
feeds can only have one author, on the other hand in Atom 1.0 feed there can be
more than one author (Check output of both format for differences in tags).
That’s
it!!! You can download the working sample of this article here.
how to create dynamic syndication data from the database?
ReplyDeleteRSS 2.0 feed does not validate
ReplyDelete