RSS is finally getting the recognition it deserves. SitePoint now publishes RSS, and large news agencies like the BBC, the New York Times and CNN also publish RSS feeds. Now, developers can integrate content from a wide range of producers within their own applications, giving users a greater incentive to return, and opening up new possibilities for application development.
This article will show you how to create a server control based on the DataList
to provide a self-contained and manageable way of consuming RSS feeds within your ASP.NET applications.
Key Takeaways
- Learn how to create a custom RSS DataList control in ASP.NET for efficient RSS feed consumption within applications, enhancing user retention and application capabilities.
- Understand the historical development of RSS, RDF, and Atom, and recognize the importance of integrating these technologies into modern web applications.
- Utilize XSLT for transforming various RSS feed formats into a unified, simple XML format that can be easily managed and displayed using the DataList control.
- Implement caching mechanisms to improve performance by storing and reusing the processed data, reducing the frequency of feed downloads.
- Discover the steps to integrate the custom RSS DataList control into ASP.NET web pages, including how to handle data binding and customize the appearance using templates.
RSS, RDF, Atom�What’s the Situation?
SitePoint’s Nathan Matias has written a Get Off Your RSS – A Quick Introduction to RSS, though there is more to know before we can start developing applications to consume RSS feeds.
First, a quick history lesson. Think back to the late 90s. The Internet had boomed, stock options were looking rosy, imaginations were firing, and “push technology” was being touted as the next leap forward. Companies like Microsoft and Netscape both integrated push clients into their browser software. Start-ups like PointCase and Marimba were selling the virtues of having information pushed towards your clients rather than having them go and seek it for themselves.
But while Active Desktop was being switched off everywhere, Userland software was pushing content in the first syndicated format, the <scriptingNews>
format. Netscape was also developing RSS, and in 1999 both formats were merged to produce RSS 0.91 and, shortly afterwards, 0.92. However, there was deep disagreement around how the format should evolve, and the specifications spilt, with RSS 2.0 being controlled first by Userland and now the Berkman Center at Harvard Law School under a creative commons license. RDF 1.0 is currently managed by a community user group.
Now Atom, yet another specification, is being proposed with the backing of Google (the now owners of Blogger) and SixApart (owners of Moveable Type and TypePad). Just recently, a merger has been offered by David Winer, the founder of UserLand software, to combine the new features in Atom with the ease of the RSS format, thereby simplifying the whole process of writing and consuming feeds and, most importantly, getting the technology adopted within the mainstream.
Today, developers have a dizzying array of specifications and formats to support if we wish to consume these feeds on our Websites. For our purposes, the different versions of “RSS” (i.e. 0.91, 0.92 and 2.0) can be treated as one; the changes to the specifications have made the core features backwards-compatible. However, RDF files use different elements and attributes to define syndicated content, so this needs to be handled differently than RSS. And, as the ever-changing Atom specification becomes more widely adopted, we also need a solution that lets us standardise all the specifications into a single format. This must be a format that we can process within our applications, but which also allows us easily to update the way in which we parse the files.
Using XSLT, which is akin to stylesheets for XML, we can parse each format and produce a flatter, simpler format that we can use to populate a DataList object on our site for display. We can alter the XSLT file without changing our code, which makes the model adaptable to any future changes to the specifications.
Creating a Customised DataList
Let’s look how our control will work. I’ve chosen the DataList
as the base control we’ll use, due to the fine-grained control it provides us over the presentation of data.
First, we take in the feed the location of which is set in a custom property on our new control. We then apply our style sheet to the incoming feed to produce a common format that we parse to populate our DataList.
As with any control to which we wish to add functionality, we need to create a class that inherits its behaviour from the base control. In our case, this is the System.Web.UI.WebControls.DataList
class. Create a new C# class file called RSSDataList.cs and begin with the following code:
namespace SitePoint
{
[ToolboxData("<{0}:RSSDataList runat=server></{0}: RSSDataList >")]
public class RSSDataList: System.Web.UI.WebControls.DataList
{
}
}
Notice the ToolboxData
attribute that’s defined for the class. This is the code that will represent our control when we use Visual Studio .NET to drop the control onto our ASP.NET Web page. If you’re using Visual Studio .NET, this is added automatically.
We need a property to store the URL of the feed we wish to view from our control:
private string _location;
[Bindable(true), Category("Behaviour"), DefaultValue("")]
public string Location
{
get
{
return _location;
}
set
{
_location = value;
}
}
The use of property accessors (get and set) is good programming practise. It allows us to control both the setting and retrieval of our new variable, while providing us with a private variable to which we along have access. We could, for instance, include validation within the set accessor for completeness.
As it stands, we have a DataList
control with an added property — the location of the URL. It’s now time to get to the nitty gritty and parse our XML files. To do this, we need to define our XSLT file and the format we’ll produce, which will be used to bind with the DataList
.
There are 3 different display objectives we wish to extract from our XML file and display: the title of a post, its link, and a description. How we derive these items is up to our stylesheet. For example, with RSS, we can add Permalinks (permanent links to resources) and date information to the description of the post. Indeed, we could build in support for a whole range of extensions and elements in our description (slash:comments
, for example).
Hence, the flattened, generic format that we’ll parse will have the following format:
<feed>
<item>
<title>Title of post</title>
<link>Link to post</link>
<description>Description of post</description>
</item>
</feed>
In addition, we need to be kind to our feed providers, and to ourselves. Downloading the feed every time we have a request will slow down our bandwidth and might prompt the provider to block our future requests. To control performance, we will employ caching to serialise the contents of our transformed feed. The object will remain in the cache for 60 minutes by default. However, there are elements within RSS called TTL (time to live), which define the exact lifetime of the feed. To parse this value, however, will add complications to our design, but it’s a way in which the control could be extended in the future.
To summarise, then, our XSLT file that converts the flavours of RSS and RDF looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:rss="http://purl.org/rss/1.0/" xmlns:xsl="https://www.w3.org/1999/XSL/Transform" xmlns:rdf="https://www.w3.org/1999/02/22-rdf-syntax-ns#">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="rss|/rdf:RDF">
<feed>
<xsl:apply-templates select="channel/item|/rdf:RDF/rss:item"/>
</feed>
</xsl:template>
<xsl:template match="channel/item|/rdf:RDF/rss:item">
<item>
<title>
<a href="{link|rss:link}">
<xsl:value-of select="title|rss:title"/>
</a>
</title>
<link>
<xsl:value-of select="link|rss:link"/>
</link>
<description>
<p><xsl:value-of select="description|rss:description"/></p>
<p><xsl:value-of select="pubDate|rss:pubDate"/></p>
</description>
</item>
</xsl:template>
</xsl:stylesheet>
This style sheet looks for the channel or item elements within both RSS and RDF files and applies a template to redisplay them. Notice that, in the description element, we have combined both the description of the post and the publishing date of the post (pubDate
). This is where you can get inventive and add support for all those extra tags to make your display shine.
To process the transformation, and bind the resulting XML to the DataList
, we create a new method called bindToRSS()
in our RSSDataList
control:
public void bindToRSS()
{
System.IO.Stream str = new System.IO.MemoryStream();
System.Xml.XPath.XPathDocument doc;
// Create the XslTransform.
System.Xml.Xsl.XslTransform xslt = new System.Xml.Xsl.XslTransform();
// Load the stylesheet that creates XML Output.
xslt.Load(System.Web.HttpContext.Current.Server.MapPath("rss.xsl"));
// Load the XML data file into an XPathDocument.
// if this is in the cache, grab it from there...
if (System.Web.HttpContext.Current.Cache["rss"+_location] == null)
{
// No cache found.
doc = new System.Xml.XPath.XPathDocument(_location);
// Add to cache.
System.Web.HttpContext.Current.Cache.Add("rss"+_location, doc, null, DateTime.Now.AddMinutes(60), TimeSpan.Zero, CacheItemPriority.High, null);
}
else
{
// Cache found.
doc = (XPathDocument)System.Web.HttpContext.Current.Cache["rss" + _location];
}
// Create an XmlWriter which will output to our stream.
System.Xml.XmlWriter xw = new System.Xml.XmlTextWriter(str, System.Text.Encoding.UTF8);
// Transform the feed.
xslt.Transform(doc, null, xw, null);
// Flush the XmlWriter and set the position of the stream to 0
xw.Flush();
str.Position = 0;
// Create a dataset to bind to the control.
DataSet ds = new DataSet();
ds.ReadXml(str);
// Select the data source, and bind.
this.DataSource = ds.Tables[0].DefaultView;
this.DataBind();
// Close the writer and thereby free the memory stream.
xw.Close();
}
We use streams to store our documents and transformations as there is every chance this control is going to be used by multiple users viewing different feeds. If we saved our results to file, we would run into problems as we tried to ensure we displayed the requested feed, and not some other user’s request that had overwritten our input! Using memory-based streams, however, each instance of our control has its own storage within the main memory, which makes it suitable for multiple user usage.
Notice how an XmlWriter
is employed to provide our stream str
with an interface that’s suitable for us to write XML. Once the transformation has been made, we need to save (or flush) the contents of the XmlWriter
to our stream as, at present, our stream is still empty. After we’ve written the XML data, the pointer position within the stream will be at the end of the data. Before we read it, we need to set this pointer back to the beginning of the stream.
Once we have filled our memory stream with XML in our flatter format, we can see why a DataList
is so suitable for this control. By creating a data set from the XML file, and binding it directly to the DataList
, we’ve parsed and made the feed available for presentation in just 4 lines of code:
// Create a dataset to bind to the control.
DataSet ds = new DataSet();
ds.ReadXml(str);
// Select the data source, and bind.
this.DataSource = ds.Tables[0].DefaultView;
this.DataBind();
Caching
Another of our design goals was to cache the feeds to maintain good performance. The cache saves the XPathDocument
instance which contains the feed specified in the Location
variable. By caching this, our page will only download the feed once per hour, rather than downloading it each and every time it is requested.
Notice that we need to grab the running instance of the cache as our control isn’t tied to any particular Web application. System.Web.HttpContext.Current
provides the currently running HttpContext
, which includes the familiar Response
and Request
objects and the Cache
object.
Giving the cache an expiration time of 60 minutes is a good idea. When we check to see if an entry exists in the cache, we can also check whether the feed has expired as, after 60 minutes, the cached entry will be removed. Hence, this is a simple method of checking and setting the cache:
if (System.Web.HttpContext.Current.Cache["rss"+_location] == null)
{
// No cache found.
}
else
{
// Cache found.
}
Now that you’ve completed the code of the control, you must compile the RSSDataList.cs
file into a .NET assembly: RSSDataList.dll
. If you don’t know how to do this, it’s covered in Kevin Yank’s article, Object Oriented C# for ASP.NET Developers.
DataList
Templates
We now have 3 elements exposed to our DataList
: title, link, and description. The display of these elements is handled within the Itemtemplate
section of the DataList
declaration. This process is very simple.
<asp:DataList ... >
<ItemTemplate>
... template definition here
</ItemTemplate>
</asp:DataList>
Within the ItemTemplate
section, we can add markup and styles. At any point at which we want to display one of our elements (title, link, or description), we add the following inline code to tell ASP.NET to insert the contents of the element:
<%# DataBinder.Eval(Container.DataItem, "foo") %>
(Here, “foo” is changed to match the element to add.)
For example, here’s a completed item template, which shows the title of a post in a large font, and the description underneath in a new paragraph break:
<sitepoint:RSSDataList runat="server">
<ItemTemplate>
<p><font size="4">
<%# DataBinder.Eval(Container.DataItem, "title") %>
</font></p>
<p>
<%# DataBinder.Eval(Container.DataItem, "description") %>
</p>
</ItemTemplate>
</sitepoint:RSSDataList>
To conclude, let’s walk through the process of consuming a feed using this new control.
Adding the Control to the Visual Studio Toolbox
- Right click on the control toolbox and select “Add / Remove Items�”
- From the Customize Toolbox dialog (shown below), click Browse� and select the assembly that contains the
RSSDataList.cs
class that holds the control: - Select the
RSSDataList
control from the list, and make sure the check box is ticked. Click OK to add the control to the toolbox.
Defining the Control in the .aspx
page
- Either drag the
RSSDataList
control onto your form, or add the following declarations to your.aspx
page:<%@ Register TagPrefix="sitepoint" Namespace="SitePoint" Assembly="RSSDataList" %>
<sitepoint:RSSDataList id="RSSDataList1" runat="server">
</sitepoint:RSSDataList> - Add the ItemTemplate we saw above to the
RSSDataList
tag:<%@ Register TagPrefix="sitepoint" Namespace="SitePoint" Assembly="RSSDataList" %>
<sitepoint:RSSDataList id="RSSDataList1" runat="server">
<ItemTemplate>
<p><font size="4">
<%# DataBinder.Eval(Container.DataItem, "title") %>
</font></p>
<p>
<%# DataBinder.Eval(Container.DataItem, "description") %>
</p>
</ItemTemplate>
</sitepoint:RSSDataList> - Using the property selector in Visual Studio, you can define the feed you whish to associate with the control through the
Location
variable:Alternatively, you can add this variable to the tag definition earlier:
<sitepoint:RSSDataList id="RSSDataList1" Location="https://www.sitepoint.com/recent.rdf" runat="server">
...
</sitepoint:RSSDataList>Or, of course, through code:
private void Page_Load(object sender, System.EventArgs e)
{
RSSDataList1.Location = "https://www.sitepoint.com/recent.rdf";
}
Binding the Feed to the Control
Finally, you need to call the method bindToRSS()
once you have set the Location
property:
private void Page_Load(object sender, System.EventArgs e)
{
RSSDataList1.Location = "https://www.sitepoint.com/recent.rdf"; RSSDataList1.bindToRSS();
}
Make sure you have your XSLT file rss.xsl
stored in the root of your application directory. That’s all there is to displaying RSS and RDF files on your site!
Frequently Asked Questions (FAQs) about RSS Datalist Control in ASP.NET
How can I bind data to a DataList control in ASP.NET?
Binding data to a DataList control in ASP.NET is a straightforward process. First, you need to create a connection to your database using SqlConnection. Then, you need to write a SQL query to fetch the data from the database. This query is executed using SqlCommand and the data is stored in a SqlDataReader. Finally, you set the DataSource property of the DataList to the SqlDataReader and call the DataBind method.
Can I customize the appearance of the DataList control?
Yes, you can customize the appearance of the DataList control in ASP.NET. You can use the properties of the DataList control to change its layout and style. For example, you can use the RepeatColumns property to specify the number of columns in the DataList, and the RepeatDirection property to specify whether the DataList displays its items in rows or columns.
How can I handle events in the DataList control?
The DataList control in ASP.NET provides several events that you can handle in your code. For example, you can handle the ItemCommand event to respond when the user clicks a button in the DataList. To handle an event, you need to write an event handler method and attach it to the event.
What is the difference between the DataList control and other data-bound controls in ASP.NET?
The DataList control is a flexible data-bound control that allows you to display data in a customizable layout. Unlike other data-bound controls like the GridView, the DataList does not provide built-in sorting and paging functionality. However, it gives you more control over the layout of the data.
How can I create an RSS feed using ASP.NET?
Creating an RSS feed in ASP.NET involves generating an XML document that conforms to the RSS standard. You can use the XmlTextWriter class to create the XML document. The document should include a channel element that contains information about the feed, and item elements that contain information about each item in the feed.
Can I use the DataList control in ASP.NET Core?
No, the DataList control is not available in ASP.NET Core. ASP.NET Core is a new framework that does not include Web Forms and its controls. However, you can achieve similar functionality using Razor Pages or MVC in ASP.NET Core.
How can I update data in a DataList control?
To update data in a DataList control, you can handle the EditCommand event to put the DataList item in edit mode, and then handle the UpdateCommand event to save the changes. You need to use the FindControl method to find the controls that contain the updated data in the DataList item.
How can I display data in a specific format in the DataList control?
You can use data binding expressions to display data in a specific format in the DataList control. For example, you can use the Eval method in a data binding expression to display a date in a specific format.
Can I display data from multiple tables in a DataList control?
Yes, you can display data from multiple tables in a DataList control. You need to write a SQL query that joins the tables, and then bind the result to the DataList.
How can I handle errors in the DataList control?
You can handle errors in the DataList control by using try-catch blocks in your code. For example, you can use a try-catch block when you execute a SQL query to handle any database errors. You can also use the OnError event of the DataList control to handle any errors that occur during data binding.
Philip is a Computer Science PhD student at Liverpool John Moores University. He's still not mastered guitar tabs, never finished Mario, and needs a haircut.