Sep 20 2006

Creating an RSS feed for your ASP.NET site

Posted by admin under ASP.NET articles

How useful a RSS feed actually is is hard for me to say something about, I personally have a hard time understanding the buzz about blogs (why should that be better than a regular website).

While the content people present in blogs might be really good - I just love Scott Guthries blog, the big problem with blogs (and I mean the actual blog applications) is categorization of data. How fun is it to try t find a specific article - to find you have to browse to the month you believe it was published. While the search engines might have been approved and categorization with Tags is becoming more popular in blog software I still think the actual navigation is pretty lame.

But for news aggregating - fine, I can buy that idea, RSS has been tightly coupled with blogs but there is no reason as to why you couldn't put up a RSS feed for your (non-blog) site. So, that's what I have decided to do - and will describe for you here.

First, we are using a ASHX handler - that technique is described in a separate article

Now lets try to fins out what RSS is about. Basically you (the website owner) should return a RSS feed - and that's simply an XML document following a certain standard, describing new articles on your site.

Lets have a look on a part of my RSS feed:



 <?xml version="1.0" encoding="UTF-8" ?> 
 <rss version="2.0">
 <channel>
  <title>ASPCode.net RRS flow</title> 
  <link>http://www.aspcode.net/articles/default.aspx</link> 
  <description>Articles about ASP.NET, C# and development with Visual Studio</description> 
  <ttl>5</ttl> 
 <item>
  <title>Creating an RSS feed for your ASP.NET site</title> 
  <link>http://www.aspcode.net/articles/l_en-US/t_default/ASP.NET/Creating-an-RSS-feed-for-your-ASP.NET-site_article_277.aspx</link> 
  <guid isPermaLink="true">http://www.aspcode.net/articles/l_en-US/t_default/ASP.NET/Creating-an-RSS-feed-for-your-ASP.NET-site_article_277.aspx</guid> 
  <description>How useful a RSS feed actually is is hard for me to say something about, I personally have a hard time understanding the buzz about blogs (why should that be better than a regular website). While the content people present in blogs might be really good - ...</description> 
  <pubDate>Wed, 30 Aug 2006 13:00:09 GMT</pubDate> 
  </item>



Lets talk a little about the different tags in the XML file.

title
The name of the channel. It's how people refer to your service
link
The url to the website
description
Phrase or sentence describing the channel
ttl
It's a number of minutes that indicates how long a channel can be cached before refreshing from the source. So, it's information for the news aggregator/reader program how often it should update it's content from the feed.

For each item(articles)

title
The header of the article
link
The url of the article
description
Short description - synopsis
guid
A string that uniquely identifies each article. Often you have unique page (url) for each article on your website (for example showart.aspx?id=123) so it's most often ok to use the link as guid.
pubDate
date when the article was published, ex format Sat, 07 Sep 2002 00:00:01 GMT


This was just a brief overview of what tags you might want to use in your RSS feed, for an extensive explaination, please go to RSS 2.0 Specification



So that's what we are gonna create - when people/programs(news aggregators) access the page rss.ashx the document should be returned as an XML file.
All action takes place in the handlers ProcessRequest

public void ProcessRequest (HttpContext context)
{
	string sTxt = BuildXmlString();
	context.Response.ContentType = "text/xml";
	context.Response.ContentEncoding = System.Text.Encoding.UTF8;

	context.Response.Write( sTxt );
	   
}


Well, maybe not so much action there, the building of the XML is done in BuildXmlString



private string BuildXmlString()
{
	string sTitle = "The title if your blog";
	string sSiteUrl = "http://www.aspcode.net";
	string sDescription = "The site is the coolest bla bla and this rss feed is the best!";
	string sTTL = "60";

	System.Text.StringBuilder oBuilder = new System.Text.StringBuilder();
	oBuilder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	oBuilder.Append("<rss version=\"2.0\"><channel>");
	
	oBuilder.Append("<title>");
	oBuilder.Append(sTitle);
	oBuilder.Append("</title>");

	oBuilder.Append("<link>");
	oBuilder.Append(sSiteUrl);
	oBuilder.Append("</link>");

	oBuilder.Append("<description>");
	oBuilder.Append(sDescription);
	oBuilder.Append("</description>");

	oBuilder.Append("<ttl>");
	oBuilder.Append(sTTL);
	oBuilder.Append("</ttl>");
	

	AppendItems(oBuilder);
		

	oBuilder.Append("</channel></rss>");
	return oBuilder.ToString();
}




This builds up the basic structure of the document, with title, description, ttl etc and now we are gonna add the actual articles - thats what happens in AppendItems



public void AppendItems(System.Text.StringBuilder oBuilder)
{
	//read from database or whatever and retrieve the 10 latest articles
	//I have a class, ObjClasses.Article and a collection
	//ObjClasses.ArticleList which does the retrieving

	ObjClasses.ArticleList oList = new ObjClasses.ArticleList();
	oList.OpenLatest(10);
	foreach( ObjClasses.Article oArt in oList )
	{
		string sTitle = oArt.Header;
		string sLink = "http://www.aspcode.net/wharver/showarticle.aspx?id=" + oArtId.ToString() ;
		string sDescription = oArt.ShortDescr;
		string sPubDate = oArt.LastModified.ToString("R");

		oBuilder.Append("<item>");

		oBuilder.Append("<title>");
		oBuilder.Append(  sTitle);
		oBuilder.Append("</title>");

		oBuilder.Append("<link>");
		oBuilder.Append(sLink);
		oBuilder.Append("</link>");

		oBuilder.Append("<guid isPermaLink=\"true\">");
		oBuilder.Append(sLink);
		oBuilder.Append("</guid>");

		oBuilder.Append("<description>");
		oBuilder.Append(sDescription);
		oBuilder.Append("</description>");

		oBuilder.Append("<pubDate>");
		oBuilder.Append(sPubDate);
		oBuilder.Append("</pubDate>");

		oBuilder.Append("</item>");


	}
}



This is everything, actually. I will still make one improvement - caching:

public void ProcessRequest (HttpContext context)
{   
	string sTxt = "";
	if ( context.Cache["RSSFEED123"] == null )
	{
		sTxt = BuildXmlString(context);
		context.Cache.Insert( "RSSFEED123", sTxt );
	}
	else
		sTxt = context.Cache["RSSFEED123"].ToString();
			
	context.Response.ContentType = "text/xml";
	context.Response.ContentEncoding = System.Text.Encoding.UTF8;
	context.Response.Write( sTxt );
}



You might spot the potential problem here - the cached string lives forever (until the webapplication restarts actually) but you can of course insert your string with a CacheDependency - or do as I do - please read the related article about ASP.NET caching control

Added: 2006-09-20
I use pretty much this exact script on this very site but after a while I found that the rss feed generated was corrupt. It turned out that I had added some articles with quotes etc and it of course broke the xml.

The fix is to add CDATA sections:



oBuilder.Append("<item>");
oBuilder.Append("<title><![CDATA[ ");
oBuilder.Append(  sTitle);
oBuilder.Append(" ]]> </title>");
oBuilder.Append("<link>");
oBuilder.Append(sLink);
oBuilder.Append("</link>");
oBuilder.Append("<guid isPermaLink=\"true\">");
oBuilder.Append(sLink);
oBuilder.Append("</guid>");
oBuilder.Append("<description><![CDATA[ ");
oBuilder.Append(sDescription);
oBuilder.Append(" ]]> </description>");
oBuilder.Append("<pubDate>");
oBuilder.Append(sPubDate);
oBuilder.Append("</pubDate>");
oBuilder.Append("</item>");

Links