When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles [1.x] [2.0]
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
Headlines from ASPWire.com
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs
















internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers
ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
Print this Page!

Windows Systems Administrator
Jupitermedia
US-CT-Darien

Justtechjobs.com Post A Job | Post A Resume

Published: Wednesday, June 6, 2007

Personalizing RSS Feeds with ASP.NET 2.0
By Erich Peterson


Introduction
Really Simple Syndication (RSS) is a common XML standard for syndaicating web content. It is typically used by content-producing sites to offer a machine-readable version of the latest headlines. For example, news sites like CNN.com and MSNBC.com offer RSS feeds for breaking news; most blog software includes RSS support that syndicates the blogger's most recent posts. Since its inception, RSS has radically increased in popularity; today it is hard to find a content-producing website that does not offer at least one RSS feed.

While RSS can be used to provide a single encompassing syndication feed for a website's content, users oftentimes are interested in RSS feeds that syndicate content catered to their specific interests. They don't necessarily want to see every article, blog post, or news item a web site offers. Instead, a particular visitor to CNN.com might only be interested in international news, whereas another might only want to track the latest business-related news headlines. Websites that provide specialized RSS feeds do so by offering different links for RSS feeds on different topics. In this article, we will look at an example of how to provide dynamic and customized RSS feeds in an ASP.NET 2.0 application. Read on to learn more!

- continued -

A Primer on RSS
RSS is an XML-based standard designed to allow web content providers to publish (syndicate) their frequently updated digital content, such as podcasts or articles, in a standard aggregated format. Commonly, RSS feeds do not contain the entirety of the content. Rather, the RSS feed usually provides just a brief description of the content, along with its title and a link to the full content. This article only lightly touches the RSS standard. For a more in-depth look at the standard and usage examples, refer to the official RSS 2.0 standard.

The following XML content illustrates the markup in a very simple RSS feed:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
   <title>ASP .NET 1.x</title>
   <link>http://example.com</link>
   <description>Everything you ever wanted to know about ASP .NET 1.x.</description>
   <copyright>Copyright 2007. All rights reserved.</copyright>

   <item>
     <title>An Extensive Examination of the DataGrid Web Control: Part 1</title>
     <description>A DataGrid control article series that will span several weeks.</description>
     <link>http://www.example.com/Articles/default.aspx?articleid=2</link>
   </item>
   <item>
     <title>.Net Data Caching</title>
     <description>In simple terms data caching is storing data in memory for quick access.</description>
     <link>http://www.example.com/Articles/default.aspx?articleid=3</link>
   </item>
  </channel>
</rss>

An RSS feed is made up of (at minimum) the following elements:

  • An <rss> root element with a version attribute (one per document)
    • Zero or more <channel> element(s), which is a logical grouping of feeds (not unlike a real TV channel)
      • A <title> element, containing the title of the channel (required).
      • A <description> element, containing the description of the channel (required).
      • A <link> element, containing a link back to the channel's main page (required).
      • A <copyright> element, containing copyright information (optional).
      • Zero or more <item> element(s) which denote the beginning of a new item within a channel; sometimes an item is known as a "story."
        • A <title> element, containing the title of the item (optional).
        • A <description> element, containing a description of the item (optional).
        • A <link> element, containing a link to the item's full content.

Along with the items listed above, the standard also specifies a number of additional optional elements. Refer to the RSS 2.0 standard for more information.

To see an example of a "real" RSS feed in action, you need look no further than this website, which uses an RSS feed to share the most recently published articles. Visit http://aspnet.4guysfromrolla.com/rss/rss.aspx to see the RSS feed. What you see when visiting an RSS feed through a browser depends on the browser you are using. Modern browsers - IE 7 and Firefox 2.0 - display RSS feeds in a standardized, rich format. Older browsers may display the RSS feed as raw XML or format the feed based on a stylesheet specified by the RSS feed. Note that each content item in the 4GuysFromRolla.com RSS feed provides a title, a link to the article, the date and time the article was published, and the article's introduction. Clicking the title of the article sends you to the full text of the article.

Scott Mitchell shared the code used for the 4Guys RSS feed in Syndicating Your Web Site's Content with RSS and ASP.NET. 4Guys provides only a single RSS feed. It could, however, break up this single RSS feed into feeds by category. That is, rather than the master RSS feed (or in addition to it), Scott could add an RSS feed for ASP.NET 1.x-specific articles, one for ASP.NET 2.0-specific articles, and so forth. This article looks at how to construct such a system. Specifically, our example website will have four article categories: ASP.NET 1.1, ASP.NET 2.0, SQL Server 2000, and SQL Server 2005. A visitor can specify the category she wants to subscribe to; the web page will then output the URL specific to that feed. Visiting that feed will dynamically generate the XML sharing the articles for the specified category.

For more information on RSS, see the RSS Wikipedia entry; use FeedValidator.org's free tools to validate that your RSS feed is well-formed and correct according to the official standard.

Building the Database Infrastructure
We need a database to house the categories and content to be syndicated. This database will contain two tables: one for the categories and one for the articles. These tables' schemas are shown below.

Note: A SQL Server 2005 Express database with the presented schema, along with all the sample code, can be downloaded at the end of this article.

Creating the Website and Necessary Web Pages
With our database tables constructed and sample data stored within them, we can now dive into the ASP.NET pages and code. We will need to first create a new web project using Visual Studio (or the free Visual Web Developer). This web application needs just two web pages:

  • Default.aspx - lists the categories in a pageable DetailsView, with a link to view the category-specific RSS feed, and
  • RSS.aspx - accepts a CategoryID value as input through the querystring (like RSS.aspx?category=CategoryID) and then emits the RSS feed XML for the content for the specified CategoryID.
The following screen shot shows the Default.aspx page when viewed through a browser.

This page was created using two SqlDataSource controls: one to bind and populate a DropDownList with rows contained within the Categories table and the other to bind and populate a DetailsView with more details about the particular category selected. The DetailsView includes a HyperLinkField with the label "RSS Feed URL" and a dynamic URL with the format ~/RSS.aspx?category=CategoryID.

The RSS.aspx page serves an RSS feed that contains the content from the specified category. Since an RSS feed is simply XML output, we do not include any HTML or Web control markup in the .aspx portion of the page. In the .aspx portion you will only find the @Page directive and the @OutputCache directive (and no other markup):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="RSS.aspx.cs" Inherits="_RSS" %>
<%@ OutputCache VaryByParam="category" Duration="120" %>

The @OutputCache directive instructs the ASP.NET engine to cache the output of this page for 120 seconds, varying the output cache by the Category querystring parameter. Caching makes sense here because articles are not likely to be created or updated extremely frequently. In fact, on 4Guys articles appear, on average, once a week. Therefore, the caching duration could feasibly be extended to several hours. For more on ASP.NET's output caching, see Caching with ASP.NET.

Let's examine the RSS.aspx page's code-behind class. Note that the following namespaces are referenced in using statements:

using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Xml;

The most important of the four namespaces, for our purposes, is System.Xml, which includes the classes we will use for generating the RSS feed's XML output. The following code is taken from the Page_Load event handler:

// find out if the query string parameter is present
if (Request.QueryString["category"] != null && Request.QueryString["category"] != "")
{
  using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString()))
  {
   using (SqlCommand cm = new SqlCommand())
   {
    // get the CategoryId from the query string
    int qsCategory = Convert.ToInt32(Request.QueryString["category"]);

    // set the conenction and query string
    cm.Connection = cn;
    cm.CommandText = "SELECT Title, Description FROM Categories WHERE " +
    "CategoryId = @CategoryId";

    // create parameter for our command and give it a value
    SqlParameter parmCategories = new SqlParameter("@CategoryId", SqlDbType.Int);
    parmCategories.Value = qsCategory;

    // add the parameter to the command object
    // and open the connection
    cm.Parameters.Add(parmCategories);
    cn.Open();

    // execute the query and return the results to a SqlDataReader
    SqlDataReader dr = cm.ExecuteReader();

    if (dr.Read())
    {
      // clear out the buffer
      Response.Clear();
      // set response content type
      Response.ContentType = "text/xml";

      // delcare and instantiate XMLTextWriter object
      XmlTextWriter xtw = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);

      // write out the XML declaration and version 1.0 info
      xtw.WriteStartDocument();

      // write out the rss xml element "rss" (required)
      xtw.WriteStartElement("rss");
      xtw.WriteAttributeString("version", "2.0");

      // write out "channel" element (required)
      xtw.WriteStartElement("channel");

      // write out title, link, and description based on the feed being requested,
      // all three elements are required
      xtw.WriteElementString("title", dr["Title"].ToString());
      xtw.WriteElementString("link", "http://www.example.com/");
      xtw.WriteElementString("description", dr["Description"].ToString());
      xtw.WriteElementString("copyright", "Copyright " + DateTime.Now.Year.ToString() + ". All rights reserved.");

      // close the connection and clear the existing parameters
      dr.Close();
      cm.Parameters.Clear();

      // prepare new query
      cm.Connection = cn;
      cm.CommandText = "SELECT ArticleId, Title, Description FROM Articles "
        + "WHERE CategoryId = @CategoryId";

      // add parameter and execute query to return article details
      SqlParameter parmArticles = new SqlParameter("@CategoryId", SqlDbType.Int);
      parmArticles.Value = qsCategory;
      cm.Parameters.Add(parmArticles);
      dr = cm.ExecuteReader();

      // Loop through the content of the database and add them to the RSS feed
      while (dr.Read())
      {
       xtw.WriteStartElement("item");
       xtw.WriteElementString("title", dr["Title"].ToString());
       xtw.WriteElementString("description", dr["Description"].ToString());
       xtw.WriteElementString("link", "http://www.example.com/default.aspx?articleid=" + dr["ArticleId"]);
       xtw.WriteEndElement();
      }
      dr.Close();

      // Close all tags
      xtw.WriteEndElement();
      xtw.WriteEndElement();
      xtw.WriteEndDocument();
      xtw.Flush();
      xtw.Close();
    }
    else
    {
      Response.Write("Non valid RSS feed URL.");
    }
   }
  }
}
else
{
  Response.Write("Non valid RSS feed URL.");
}

I know there's a lot of code above, but it is not that complicated. First, we check to make sure the Category query string parameter is present. Information about the specified category is retrieved from the Categories table. Once this information has been retrieved, an XmlTextWriter object is used to programmatically create the XML corresponding to the RSS feed. The XmlTextWriter class contains many useful methods for outputting XML, such as the WriteStartDocument method, which outputs the <?xml ?> markup that signifies the start of an XML document.

<?xml version="1.0" encoding="utf-8"?>

There's also the WriteStartElement method, which will write out the opening tag of an element, given the name of the element. In our case, the first time we call this method we pass the string "rss". This will result in the opening tag <rss> to be outputted. Furthermore, the WriteAttributeString method allows us to add an attribute to the current element. This method is used to set the <rss> element's version attribute value to "2.0". Finally, the WriteEndElement method is used to close the nearest open element.

Returning to our code's flow of execution, once we have outputed all the required XML elements, we query the database again for specific articles within the specified category, loop through the results, and output the desired RSS elements (e.g. <item>, <title>, <description>, and <link>) for each article. If we were to really implement this in a real-world setting, one would want to probably add another field to the Articles database table named DateOfPublication (or something similar). With such a field, we would update the database query to return just the ten most recently published articles:

SELECT TOP 10 ArticleId, Title, Description, DateOfPublication
FROM Articles
WHERE CategoryId = @CategoryId
ORDER BY DateOfPublication DESC

We could also include the date published information within each RSS feed item by using the optional <pubDate> element.

Because some browsers such as IE 7 and Firefox 2 have built in RSS readers, if a user followed one of your RSS feed links directly in their browser, they should see a nice representation of the RSS feed's content—like the one shown in the following screen shot.

Conclusion
Creating personalized RSS feeds are not at all difficult to implement and provide the user with a means to subscribe to RSS feeds focused on their interests. While this article focused on creating customized RSS feeds for a single, specific category, with a bit more effort you could update the RSS.aspx page to accept a variable number of Category querystring parameters, allowing users to create a single RSS feed that is a conglomoration of one or more categories. I invite the interested reader to tackle this problem as an exercise.

Happy Programming!

  • By Erich Peterson


    Attachments:

  • Download the demo application used in this article

  • Windows Internet Technology | ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

    Solutions
    Whitepapers and eBooks
    Microsoft Article: Will Hyper-V Make VMware This Decade's Netscape?
    Microsoft Article: 7.0, Microsoft's Lucky Version?
    Microsoft Article: Hyper-V--The Killer Feature in Windows Server 2008
    Avaya Article: How to Feed Data into the Avaya Event Processor
    Microsoft Article: Install What You Need with Windows Server 2008
    HP eBook: Putting the Green into IT
    Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
    Avaya Article: Setting Up a SIP A/S Development Environment
    IBM Article: How Cool Is Your Data Center?
    Microsoft Article: Managing Virtual Machines with Microsoft System Center
    HP eBook: Storage Networking , Part 1
    Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
    MORE WHITEPAPERS, EBOOKS, AND ARTICLES
    Webcasts
    Intel Video: Are Multi-core Processors Here to Stay?
    On-Demand Webcast: Five Virtualization Trends to Watch
    HP Video: Page Cost Calculator
    Intel Video: APIs for Parallel Programming
    HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
    Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
    MORE WEBCASTS, PODCASTS, AND VIDEOS
    Downloads and eKits
    Sun Download: Solaris 8 Migration Assistant
    Sybase Download: SQL Anywhere Developer Edition
    Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
    Red Gate Download: SQL Compare Pro 6
    Iron Speed Designer Application Generator
    MORE DOWNLOADS, EKITS, AND FREE TRIALS
    Tutorials and Demos
    How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
    eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
    IBM Article: Collaborating in the High-Performance Workplace
    HP Demo: StorageWorks EVA4400
    Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
    Microsoft How-to Article: Get Going with Silverlight and Windows Live
    MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES