Building an RSS feed made simple
posted by
Jeff
Those little orange XML icons are everywhere. How much will people think you suck if your site doesn't have one? Syndicate your content today or be the target of jokes at your next party.
RSS stands for "Really Simple Syndication," and it's all the rage. The idea
is pretty simple. Output some XML to the Web that content aggregators and other
sites can consume and display. If you have a normal routine of sites you visit
with frequent content updates (news, blogs, whatever), and each site has an RSS
feed, you can at a glance see what's new at all of these sites with an
aggregator.
I won't go into detail about how to use these feeds, but
there's a great little piece over at
LockerGnome that tells you all about it. You'll also find links to
aggregators, and if you find one you like, you'll find yourself subscribing to
feeds all over the place.
The benefit to you is that
you might just attract visits to your site from people who might not otherwise
go there because they can see what's new at many sites without having to wade
through all of their bookmarks. And hey, if you're putting out some kind of list
of headlines on your site, you probably already have the data access code
written. Now you just need to present it as XML.
XML you care about
Be honest, unless you're in a corporate environment writing code that moves data
around between different systems, you probably don't care all that much about
XML and you're tired of hearing Bill Gates say it will save the world. You'll be
happy to know, however, that this is one of those situations where two different
systems are sharing data, the first system being your Web site and the second
being a content aggregator or another site, or whatever.
In case you've
been living under a rock, XML stands for Extensible Markup Language, a nifty way
to present data in a format that humans can sort of read and machines can
consume. It's basically just self-describing data that looks a lot like HTML,
only you need to follow a careful structure. An RSS feed is an XML document that
has a bunch of content data.
The RSS specification
While you can use XML to pretty much present any data in any way, naturally our fancy little
content aggregators and the like are going to expect that it be in a certain
format. So before we look at the specification, let's first look at a spot of
XML from this very site's NewsWire feed:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>uberASP.Net NewsWire</title>
<link>http://www.uberasp.net/newswire.aspx</link>
<description>The latest headlines and articles from the world of ASP.NET, Microsoft's Web development platform.</description>
<copyright>(c) 2004, POP World Media, LLC. All rights reserved.</copyright>
<ttl>5</ttl>
<item>
<title>Using HttpModules to send the right data format to the client</title>
<description>The same data might need to be presented in many different formats, including HTML, XML, rich text, or even
an Excel file. Through the use of HttpModules, your site will serve the right kind of data every time.</description>
<link>http://www.uberasp.net/GetArticle.aspx?id=15</link>
<pubDate>Mon, 12 Jan 2004 04:48:34 GMT</pubDate>
</item>
<item>
<title>Going solo and running your own consulting business: Is it for you?</title>
<description>Columnist explores the ups and downs of being your own boss.</description>
<link>http://www.uberasp.net/GetArticle.aspx?id=14</link>
<pubDate>Mon, 12 Jan 2004 03:48:35 GMT</pubDate>
</item>
<item>
<title>Use an HttpHandler to stop bandwidth leeching of your images</title>
<description>HttpHandlers make it easy to handle certain file types with a simple interface that anyone can write
code for.</description>
<link>http://www.uberasp.net/GetArticle.aspx?id=13</link>
<pubDate>Fri, 09 Jan 2004 06:14:21 GMT</pubDate>
</item>
</channel>
</rss>
Pretty exciting, eh? There's a lot to learn about XML, but frankly you don't
need to learn much to understand what's going on here. The document starts with
the required XML declaration, and from there a series of tags define the data
with plain everyday words you know.
Now go check out the
RSS 2.0
Specification, and you can see why we have included the elements in this
document. The big picture "channel" requires only three elements: title, link
and description. We've added description and ttl ("time to live," which tells
aggregators how long before the data is "old") because, well, because we want
to.
The next important part of the spec is what you put in each item. The only
thing required here is the title or description. We're using both, plus a link
back to the article (because we want people to read the entire story, duh), and
the pubDate element so the end-user can see how new the headline is.
The spec gets pretty detailed about what you can add and how to do it.
Because XML is supposed to be extensible, you aren't limited to just the
specified elements. You can add others as well, provided you specify a namespace
and the overall document meets the specification. XML namespaces aren't
complicated, but in the interest of keeping things simple, we won't go into it
here.
Writing an XML document the .Net way
If you've been using the .Net Framework for even a week, you know that the
kids in Redmond really thought of almost everything, so they're not going to
make you concatenate huge strings to build an XML document. For our example,
we're going to create a new page on our site called NewsWire.aspx and use that
as the URL for our RSS feed. We're going to make the .aspx file contain only two
lnes:
<%@ Page Codebehind="NewsWire.aspx.cs" Inherits="UberAspNet.RSS.NewsWire" EnableViewState="false" %>
<%@ OutputCache Duration="300" VaryByParam="none" %>
The first line you've seen before. The second line tells ASP.NET to cache
the entire page in memory and not run the code until 300 seconds have passed.
You can put whatever value you want here, but if the data you're going to
display changes infrequently, there's no harm really in cranking it up. Cached
output is a lot faster than executing code and hitting a database. The rest of
the .aspx file contains nothing. No HTML, XML or links to nudies.
Frankly, the code-behind isn't that complicated either. Here are the goods:
C#
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Web;
using System.Xml;
namespace UberAspNet.RSS
{
public class NewsWire : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
Response.Clear();
Response.ContentType = "text/xml";
XmlTextWriter objX = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);
objX.WriteStartDocument();
objX.WriteStartElement("rss");
objX.WriteAttributeString("version","2.0");
objX.WriteStartElement("channel");
objX.WriteElementString("title", "uberASP.Net NewsWire");
objX.WriteElementString("link","http://www.uberasp.net/newswire.aspx");
objX.WriteElementString("description","The latest headlines and articles from the world of ASP.NET, Microsoft's
Web development platform.");
objX.WriteElementString("copyright","(c) 2004, POP World Media, LLC. All rights reserved.");
objX.WriteElementString("ttl","5");
SqlConnection objConnection = new SqlConnection(ConfigurationSettings.AppSettings["MyConnectionString"]);
objConnection.Open();
string sql = "SELECT TOP 10 Title, Summary, ArticleID, PostTime FROM Articles ORDER BY PostTime DESC";
SqlCommand objCommand = new SqlCommand(sql, objConnection);
SqlDataReader objReader = objCommand.ExecuteReader();
while (objReader.Read())
{
objX.WriteStartElement("item");
objX.WriteElementString("title",objReader.GetString(0));
objX.WriteElementString("description",objReader.GetString(1));
objX.WriteElementString("link","http://www.uberasp.net/GetArticle.aspx?id=" + objReader.GetInt32(2).ToString());
objX.WriteElementString("pubDate", objReader.GetDateTime(3).ToString("R"));
objX.WriteEndElement();
}
objReader.Close();
objConnection.Close();
objX.WriteEndElement();
objX.WriteEndElement();
objX.WriteEndDocument();
objX.Flush();
objX.Close();
Response.End();
}
}
}
VB .Net
Imports System
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Text
Imports System.Web
Imports System.Xml
Namespace UberAspNet.RSS
Public Class NewsWire
Inherits System.Web.UI.Page
Private Sub Page_Load(sender As Object, e As System.EventArgs)
Response.Clear()
Response.ContentType = "text/xml"
Dim objX As New XmlTextWriter(Response.OutputStream, Encoding.UTF8)
objX.WriteStartDocument()
objX.WriteStartElement("rss")
objX.WriteAttributeString("version", "2.0")
objX.WriteStartElement("channel")
objX.WriteElementString("title", "uberASP.Net NewsWire")
objX.WriteElementString("link", "http://www.uberasp.net/newswire.aspx")
objX.WriteElementString("description", "The latest headlines and articles from the world of ASP.NET,
Microsoft's Web development platform.")
objX.WriteElementString("copyright", "(c) 2004, POP World Media, LLC. All rights reserved.")
objX.WriteElementString("ttl", "5")
Dim objConnection As New SqlConnection(ConfigurationSettings.AppSettings("MyConnectionString"))
objConnection.Open()
Dim sql As String = "SELECT TOP 10 Title, Summary, ArticleID, PostTime FROM Articles ORDER BY PostTime DESC"
Dim objCommand As New SqlCommand(sql, objConnection)
Dim objReader As SqlDataReader = objCommand.ExecuteReader()
While objReader.Read()
objX.WriteStartElement("item")
objX.WriteElementString("title", objReader.GetString(0))
objX.WriteElementString("description", objReader.GetString(1))
objX.WriteElementString("link", "http://www.uberasp.net/GetArticle.aspx?id=" + objReader.GetInt32(2).ToString())
objX.WriteElementString("pubDate", objReader.GetDateTime(3).ToString("R"))
objX.WriteEndElement()
End While
objReader.Close()
objConnection.Close()
objX.WriteEndElement()
objX.WriteEndElement()
objX.WriteEndDocument()
objX.Flush()
objX.Close()
Response.End()
End Sub
End Class
End Namespace
First we show which namespaces we'll need. System.Text is necessary because
we're accessing the Encoding class. Naturally since we're creating XML, we also
need System.Xml.
Once we get to the actual Page_Load processing, we clear the Response object
and set its ContentType to "text/xml." Then we create an XmlTextWriter object
that will do all of the heavy lifting. In our case, we're outputting it to
Response.OutputStream, but you could just as easily output to a FileStream
object and save it as a file.
The rest of the code reads a lot like the output that it will create. We must
start the document with the XmlTextWriter's WriteStartDocument() method and end
with the WriteEndDocument() method. The first line that declares this as an XML
document is created for us. If we're going to create an element that
doesn't have any child nodes, we simply use the WriteElementString() method. If
the element will have child nodes, we have to start it with the
WriteStartElement() method and end it with the WriteEndElement().
The only thing you really need to watch for here is the fact that, per the
specification, we need to add an attribute to the opening rss element that
indicates what version of RSS we're using. As soon as we've called
WriteStartElement(), we call the WriteAttributeString() method to insert what
will output as version="2.0."
The data access code should look familiar enough. We'll get a DataReader from
the database and keep calling its Read() method and create item elements filled
with our title, description, link and pubDate. Notice that for the pubDate we
specify a format string for the date, in this case, "R" for the long RFC 822
format required by the spec. This time should be UTC (formerly known as GMT),
but that will depend on how you're storing it.
Once we've written all of our tags out, we'll call the Flush() and Close()
methods of the XmlTextWriter and then call the Response object's End() method to
send it all of to the client. That's it!
We can for the most part trust that the XmlTextWriter is doing things right
in terms of creating well-formed XML, but just to make sure you're not violating
the specification,
there are a number of validators to check your work. You should also feed
your finished feed into some
popular RSS readers/content aggregators, just to make sure. Some of them
don't follow the spec as well as they should though, so while you might have a
valid feed, you won't always have a valid consumer.
It's also way cool and trendy to mark your feed with a little
icon, so
feel free to save it and use it in your own project.
©2013, POP World Media, LLC. All rights reserved
Legal, privacy, terms of service