William Duffy

Glasgow Based C# ASP.NET Web Developer

How to consume an XML feed in ASP.NET – RSS

XML is the standard for distributing content on the internet, however it can prove a challenge when trying to consume and handle the data retrieved from an XML document. This is the first in a two part series on consuming and displaying XML content on your own website. We will be using XPathDocument and XPathNavigator to select the information we want from the XML document and a simple repeater to display the information within our own website. I will also show a ridiculously easy technique that can be used to cache the consumed content so that every request to your site does not require a round trip to the XML document. Part one will use an RSS feed as the XML document, part two will use the same techniques to consume a Twitter feed.

We will be performing the following steps to display the RSS feed.

  1. Setting up the current project in Visual Studio
  2. Create a control for displaying the RSS feed data
  3. Make the control reusable
  4. Request the remote RSS feed and bind it to a repeater
  5. Handle each individual ItemDataBound event in the repeater
  6. Cache the results of the RSS feed request

Let’s get started.

Setting up the current project in Visual Studio

First, open Visual Studio and create a new website. Name the website remote-xml.
(i.e. C:sitesremote-xml)
remotexml-1

Your new website should have a default structure of App_Data, Default.aspx and web.config. You can delete the App_Data folder if you wish, we will not be using it in this tutorial.
remotexml-2

Create a new folder called App_Code. Then create a new folder called controls. Within the controls folder add a new control called rss-feed.ascx.
remotexml-3

Open Default.aspx and add the new rss-feed.ascx control to it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register src="controls/rss-feed.ascx" tagname="RssFeed" tagprefix="wd" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
 
        <wd:RssFeed ID="ctrRssFeed" runat="server" />
 
    </div>
    </form>
</body>
</html>

Create a control for displaying the RSS feed data

Now we need to write the rendering markup for this control. Open the new control and add a heading and a repeater to its markup. The repeater will need an ItemTemplate and SeparatorTemplate.
ItemTemplate : This will hold the controls that display the common RSS components (title, description and link)
SeparatorTemplate: This will be rendered between each ItemTemplate in the repeater

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<h1>My RSS Feed</h1>
 
<asp:Repeater ID="rptRssFeed" runat="server">
    <ItemTemplate>
        <div>
            <asp:Literal ID="litTitle" runat="server" /><br />
            <asp:Literal ID="litDescription" runat="server" /><br />
            <asp:HyperLink ID="hypLink" Text="View" runat="server" />
        </div>
    </ItemTemplate>
    <SeparatorTemplate>
        <hr />
    </SeparatorTemplate>
</asp:Repeater>

When we bind our RSS feed to the repeater we will want to handle each item that is bound to the repeater. In order to do this we need to handle the OnItemDataBound event. Let’s add the handler for this event to our repeater.

1
<asp:Repeater ID="rptRssFeed" OnItemDataBound="rptRssFeed_ItemDataBound" runat="server">

We will also need to add the event handler code to the codebehind file.

1
2
3
4
protected void rptRssFeed_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
 
}

You can style the repeater’s item template however you wish. For example, if you want the title of each feed item to be a heading you can alter the ItemTemplate to include the required html.

1
2
3
4
5
6
7
8
9
...
    <ItemTemplate>
        <div>
                <h3><asp:Literal ID="litTitle" runat="server" /></h3>
                <asp:Literal ID="litDescription" runat="server" /><br />
                <asp:HyperLink ID="hypLink" Text="View" runat="server" />
        </div>
    </ItemTemplate>
...

If you run your code now you should see something similar to the following, not much to look at but better than an exception!
remotexml-4

Make the control reusable

The control is not much use unless it can be reused with different RSS feeds. To do this we will expose a property of the control that allows setting of the RSS url at the point of creation, or even dynamically if you choose to do so!

Add the following property to the codebehind file of the control

1
2
3
4
5
6
private string _feedUrl;
public string FeedUrl
{
    get { return _feedUrl; }
    set { _feedUrl = value; }
}

Now you can specify the RSS feed in the declarative markup of your ASPX page.

1
<wd:RssFeed ID="ctrRssFeed" FeedUrl="http://www.wduffy.co.uk/blog/feed/" runat="server" />

Request the remote RSS feed and bind it to a repeater

The control is now ready to display the contents of the RSS Feed. So we need to request it. In the Page_Init event of the control we will use the XPathDocument to load the feed and return an XPathNavigator. The XPathDocument takes a single argument in its constructor; the location of an XML file. I have used my own RSS feed as an example, but you can swap this for your own if you wish. Calling CreateNavigator on the XPathDocument returns an XPathNavigator, which allows easy traversal of the RSS feed’s XML tree using XPath.

We will be using the System.Xml and System.Xml.XPath namespaces so make sure you include these in your control’s using statement list.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
using System.Xml;
using System.Xml.XPath;
 
public partial class controls_rss_feed : System.Web.UI.UserControl
{
 
    private string _feedUrl;
    public string FeedUrl
    {
        get { return _feedUrl; }
        set { _feedUrl = value; }
    }
 
    private XmlNamespaceManager _xmlnsm;
 
    protected void Page_Init(object sender, EventArgs e)
    {
        XPathNavigator xpn = new XPathDocument(_feedUrl).CreateNavigator();
        _xmlnsm = XmlHelper.GetXmlNameSpaceManager(xpn);
 
        rptRssFeed.DataSource = xpn.Select("/x:rss/x:channel/x:item", _xmlnsm);
        rptRssFeed.DataBind();
    }
 
    protected void rptRssFeed_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
 
    }
 
}

One thing to note is that we are creating an XmlNamespaceManager object. If you look at where the repeater datasource is being set you will see the .Select query uses x: to resolve nodes in the XML tree (we set x: to the default namespace when creating the XmlNamespaceManager). Also notice that the _xmlnsm object is in the global scope of the control. This is because we will use it again within each of the raised ItemDataBound events.

The XmlNameSpaceManager is required when using XPath to ensure that namespaces are properly resolved during queries. Understanding XML namespaces is outwith the scope of this tutorial but I would recommend you check out this simple guide on W3Schools. In the meantime, create a new Class in the App_Code folder called XmlHelper. Make this class static and add the following static method to it for easy creation of future XmlNamespaceManager objects. If you don’t understand what this code does don’t worry, just copy paste it into the XmlHelper file you just created.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.XPath;
 
public static class XmlHelper
{
 
    public static XmlNamespaceManager GetXmlNameSpaceManager(XPathNavigator xpn)
    {
        xpn.MoveToFollowing(XPathNodeType.Element);
 
        XmlNamespaceManager xmlnsm = new XmlNamespaceManager(xpn.NameTable);
        xmlnsm.AddNamespace("x", xpn.NamespaceURI);
 
        foreach (KeyValuePair<string, string> xns in xpn.GetNamespacesInScope(XmlNamespaceScope.All))
            xmlnsm.AddNamespace(xns.Key, xns.Value);
 
        return xmlnsm;
    }
 
}

Handle each individual ItemDataBound event in the repeater

Now that we have the control’s repeater marked up and the XPathNavigator is bound to it’s DataSource we need to display the values of each item. Within the rptRssFeed_ItemDataBound event handler we will work with the XPathNavigator object (which is passed as the current dataitem) to extract the nodes we need and display their data in the repeater’s controls.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void rptRssFeed_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        XPathNavigator xpn = (XPathNavigator)e.Item.DataItem;
        Literal litTitle = (Literal)e.Item.FindControl("litTitle");
        Literal litDescription = (Literal)e.Item.FindControl("litDescription");
        HyperLink hypLink = (HyperLink)e.Item.FindControl("hypLink");
 
        litTitle.Text = xpn.SelectSingleNode("x:title", _xmlnsm).Value;
        litDescription.Text = xpn.SelectSingleNode("x:description", _xmlnsm).Value;
        hypLink.NavigateUrl = xpn.SelectSingleNode("x:link", _xmlnsm).Value;
    }
}

Cache the results of the RSS feed request

All that’s left to do is add a single line of code to ensure that the RSS feed is not requested every time your website gets a visitor. On the control’s .ascx page below its main <%@ Control … %> declaration simply add the following line to cache the feed for 60 minutes, after which a brand new request will be made. (The duration property takes its value in seconds)

1
<%@ OutputCache Duration="3600" VaryByParam="none" %>

Conculsion

Hopefully you now have a control that will read a remote RSS feed, render its contents and cache the output. You should be able to use these same techniques to query any XML file and render it’s contents; something that the next part of this tutorial will cover.


Tagged as , , , , + Categorized as ASP.NET, C#

28 Comments

  1. Nice guide. The simplicity of fetching and caching the RSS feed was awsome!

  2. Thanks. Great job. There is one small typo in your Page_Init. The second parameter to the xpn.Select call should be _xmlnsm and not _xlmnsm.

  3. Nice catch Steve, thanks for the heads up. Typo corrected.

  4. Hi,

    We have this XLINQ which makes XML querying very very easy and effective. You can try that to achieve better results.

    Thanks,
    Thani

  5. Pretty good…but you could avoid manually parsing the xml by using a SyndicationFeed:
    using (XmlReader reader = XmlReader.Create(uri))
    {
    SyndicationFeed rss = SyndicationFeed.Load(reader);
    }

    and voila! You have a standard strongly typed .Net access to the feed. You’ll need to reference System.ServiceModel.Web though.

  6. Simple Nice implementation.

  7. Nice tutorial. In your OutputCache directive, the Duration attribute is in seconds, so your example would be cached for 60 seconds, not 60 minutes (which would be 3,600 seconds).

  8. Can’t say I understood it all, but I did catch the use of “it’s” in your narrative a few times where you meant “its”.

  9. Here’s another option using Linq To XML. No need for XPath or the helper class.

    rss-feed.cs
    public string FeedUrl { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
    XElement rootElement = XElement.Load(FeedUrl);
    var feedItems = rootElement.Descendants(“item”).Select(item =>
    new
    {
    Title = (string)item.Element(“title”),
    Description = (string)item.Element(“description”),
    Link = (string)item.Element(“link”)
    });
    rptRssFeed.DataSource = feedItems;
    rptRssFeed.DataBind();
    }

    rss-feed.aspx
    My RSS Feed

    <asp:Literal ID=”litTitle” Text=” runat=”server” />

    <asp:Literal ID=”litDescription” Text=” runat=”server” />
    <asp:HyperLink ID=”hypLink” Text=”View” NavigateUrl=” runat=”server” />

  10. Thanks for all the comments guys.

    @David Johnson @Thanigiainathan I wrote the code to target Version 2.0 of the .NET framework that’s why I chose not to use LINQ. But should anyone wish to target a newer version of the framework the examples you provided should be a good start.

    @ashic The synication feed would indeed be a good option and I will give it some serious thought if I have to write similar code in the future.

    @Lee C. Nice catch I’ve updated the code to reflect your comment.

  11. This is such an awesome Tutorial. I am literally learning C# & ASP.Net on the fly here. The ASP.Net Team and the MSDN team have been such a great help. This is one of the projects I’m currently handling at the office and this has taught me a lot all the while saving me a massive amount of time.

    Now I just need to create the ability to allow people to subscribe to my site. Thanks very much!!

    theaspkid

  12. How can I get all feeds? For example if the weblog has 10 feed in main page this reader show us 10 feed.

  13. Kad1r, the control is designed to consume a single feed. If there are 10 feeds then put 10 copies of the control on your page, each with the url of a different feed.

  14. Hmm. I get it. Thanks.

  15. Sorry, I cant get this to work, I keep getting the error message ‘Unable to connect to the remote server’ in the page_init.

    Any ideas why ?

  16. Hi Majit, the error you are recieving suggests there is a proxy between your code and the remote server which is refusing the connection. I’d speak to you network administrator and see if they are blocking the request.

  17. Looks like a well written write up. I am really new at this, and am developing a site in VB. Can I just have the page I want to run this in be C# and have the rest of the pages left in VB?

  18. Hi WIll and everyone

    Would it be possible to extracting or removing some text from the output of this control?
    If so, do I need to use any Class Libraries to ensure that this is successful? ListItem?

  19. Hi Matt, I’m not sure exactly what your asking. Can you give a little more detail on what you are trying to achieve?

  20. Sure. Basically, I have a databse containing a list of academic papers and associated keywords. Based on the paper selected by the user, I want to find a way of customising the RSS output so that it is reduced to showing only the news items containing the keywords from the user’s selected paper (e.g. containing the keywords ‘mobile’, ‘laptop’ or ‘interface’) and not any other news items which don’t contain any for these keywords.

  21. Hi Matt,

    The logic for this should not be in the consumer, it should be on the distributor. As an example, if the file that serves the rss feed is called rss.aspx, then this is where the logic to filter results should be. Perhaps by allowing a querystring to be passed by the consumer (rss.aspx?keyword=mobile). If you really want it to be in the consumer you can look into XPath to filter, but you will need to make sure you remove the caching if the query can vary. Check out W3 Schools to get started with XPath.

  22. Varun Maggo says:

    Nice Article!

    Simple yet sophisticated!

  23. Awesome post!!!
    Just followed your illustration and my site was up and running consuming the RSS feeds.

    Thanks you once again!!!

  24. Cool! Thanks for this!
    There could be another more classical solution (simply parse the XML content) and populate a generic object. More details in this post: http://codehelp.smartdev.eu/2011/03/06/gereric-xml-object-read-any-xml-document-and-populate-a-asp-net-object-consume-xml-feeds/.

  25. Thanks for this tutorial. This is exactly what I’m looking for for a class project

  26. Dear William,

    I’m an absolute beginner, so I’m always looking for clear examples of good code as well as good tutorials. Yours is among the best I’ve found. It is sweet when it works.

    Thank you.

  27. Fantastic!! Just what I was looking for, solved my issue. Should add ads to your site so that people who benefit from your solution click on them. :)

Trackbacks & Pingbacks

  1. Hyperlink asp control doesn't appear when set - C# / C Sharp answers

    [...] re: Hyperlink asp control doesn’t appear when set It’s OK, I’ve solved this by using a better a approach – using Repeaters, Literals and Hyperlinks. For the benefit of newbies to rss, just like me, this is the site I used: http://www.wduffy.co.uk/blog/how-to-…/#comment-5101 [...]

Leave a Reply