Reading and Displaying RSS Feed in a Silverlight DataGrid

Posted by: Suprotim Agarwal , on 1/3/2009, in Category Silverlight 2, 3, 4 and 5
Views: 31050
Abstract: The SyndicationFeed class in Silverlight 2 makes it easy to parse the feed response. The process of reading a feed is as simple as reading a RSS/ATOM feed using the WebClient class, load the stream into the SyndicationFeed class and bind it to a Silverlight UI. The parsing is done by the SyndicationFeed class.
Reading and Displaying RSS Feed in a Silverlight DataGrid
 
The SyndicationFeed class in Silverlight 2 makes it easy to parse the feed response. The process of reading a feed is as simple as reading a RSS/ATOM feed using the WebClient class, load the stream into the SyndicationFeed class and bind it to a Silverlight UI. Let us see how to read and display feed in a Silverlight control:
Step 1: Open Visual Studio 2008 > File > New Project > Select the language (C# or VB.NET) > Select ‘Silverlight’ in the Project Types > from the templates, select ‘Silverlight Application’.
Step 2: Type a name (ConsumingRSS) and location for the project> click OK.
Choose the first option ‘Add a new ASP.NET Web project to the solution to host Silverlight’ and the project type as ‘ASP.NET Web Site’ and click OK. You will see that two projects are created: ConsumingRSS.Web and ConsumingRSS.
Step 3: Right click ConsumingRSS project> Add Reference > .NET Tab > Add a reference to System.ServiceModel.Syndication. In the Page.xaml.cs or vb add the following namespaces:
C#
using System.ServiceModel.Syndication;
using System.IO;
using System.Collections.Generic;
using System.Linq;
 
VB.NET
Imports System.ServiceModel.Syndication
Imports System.IO
Imports System.Collections.Generic
Imports System.Linq
Now drag and drop a TextBox, a Button and a DataGrid control from the toolbox to the Page.xaml. After rearranging these controls in the Grid, the markup will look similar to the following:
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls.Data"  x:Class="ConsumingRSS.Page"
    xmlns="http://schemas.microsoft.com/winfx/
2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBox x:Name="txtFeedLoc" Width="450" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" ></TextBox>
        <Button x:Name="btnFetch" Grid.Row="0" Content="Fetch RSS" Width="100" HorizontalAlignment="Left" Grid.Column="1"  Click="btnFetch_Click"></Button>
        <data:DataGrid x:Name="dGrid" AutoGenerateColumns="False" IsReadOnly="True" CanUserSortColumns="True" Grid.Row="1" Grid.ColumnSpan="2">
       </data:DataGrid>
    </Grid>
</UserControl>
 
If you observe, a click handler for the Button has been created. On the click event, we read the Feed URI from the textbox. The entire code is listed below:
C#
using System;
using System.Xml;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.ServiceModel.Syndication;
using System.IO;
using System.Collections.Generic;
using System.Linq;
 
 
namespace ConsumingRSS
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
           
        }
 
        protected void LoadRSS(string uri)
        {
            WebClient wc = new WebClient();           
            wc.OpenReadCompleted +=new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
            Uri feedUri = new Uri(uri, UriKind.Absolute);
            wc.OpenReadAsync(feedUri);
        }
 
        private void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                txtFeedLoc.Text = "Error in Reading Feed. Try Again later!!";
                return;
            }
            using (Stream s = e.Result)
            {
                SyndicationFeed feed;
                List<SyndicationItem> feedItems = new List<SyndicationItem>();
 
                using (XmlReader reader = XmlReader.Create(s))
                {
                    feed = SyndicationFeed.Load(reader);
                    foreach (SyndicationItem feedItem in feed.Items)
                    {
                        feedItems.Add(feedItem);
                    }
                    var posts = from item in feedItems
                                select new RSSFeed()
                                {
                                    Title = item.Title.Text,
                                    NavURL = item.Links[0].Uri.AbsoluteUri,
                                    Description = item.Summary.Text
                                };
                    dGrid.ItemsSource = posts;                   
                    dGrid.Visibility = Visibility.Visible;
                }               
            }
        }
 
        private void btnFetch_Click(object sender, RoutedEventArgs e)
        {
            if(txtFeedLoc.Text != String.Empty)
                LoadRSS(txtFeedLoc.Text.Trim());
        }
    }
 
    public class RSSFeed
    {
        public string Title { get; set; }
        public string NavURL { get; set; }
        public string Description { get; set; }
    }
 
}
 
VB.NET
Imports System
Imports System.Xml
Imports System.Net
Imports System.Windows
Imports System.Windows.Controls
Imports System.ServiceModel.Syndication
Imports System.IO
Imports System.Collections.Generic
Imports System.Linq
 
 
Namespace ConsumingRSS
      Partial Public Class Page
            Inherits UserControl
            Public Sub New()
                  InitializeComponent()
 
            End Sub
 
            Protected Sub LoadRSS(ByVal uri As String)
                  Dim wc As New WebClient()
                  AddHandler wc.OpenReadCompleted, AddressOf wc_OpenReadCompleted
                  Dim feedUri As New Uri(uri, UriKind.Absolute)
                  wc.OpenReadAsync(feedUri)
            End Sub
 
            Private Sub wc_OpenReadCompleted(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs)
                  If e.Error IsNot Nothing Then
                        txtFeedLoc.Text = "Error in Reading Feed. Try Again later!!"
                        Return
                  End If
                  Using s As Stream = e.Result
                        Dim feed As SyndicationFeed
                        Dim feedItems As List(Of SyndicationItem) = New List(Of SyndicationItem)()
 
                        Using reader As XmlReader = XmlReader.Create(s)
                              feed = SyndicationFeed.Load(reader)
                              For Each feedItem As SyndicationItem In feed.Items
                                    feedItems.Add(feedItem)
                              Next feedItem
                              Dim posts = _
                                    From item In feedItems _
                                    Select New RSSFeed()
                                                      item.Links(0).Uri.AbsoluteUri, Description = item.Summary.Text
                                                      item.Title.Text, NavURL = item.Links(0).Uri.AbsoluteUri, Description
                                                      Title = item.Title.Text, NavURL
                              dGrid.ItemsSource = posts
                              dGrid.Visibility = Visibility.Visible
                        End Using
                  End Using
            End Sub
 
            Private Sub btnFetch_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
                  If txtFeedLoc.Text <> String.Empty Then
                        LoadRSS(txtFeedLoc.Text.Trim())
                  End If
            End Sub
      End Class
 
      Public Class RSSFeed
            Private privateTitle As String
            Public Property Title() As String
                  Get
                        Return privateTitle
                  End Get
                  Set(ByVal value As String)
                        privateTitle = value
                  End Set
            End Property
            Private privateNavURL As String
            Public Property NavURL() As String
                  Get
                        Return privateNavURL
                  End Get
                  Set(ByVal value As String)
                        privateNavURL = value
                  End Set
            End Property
            Private privateDescription As String
            Public Property Description() As String
                  Get
                        Return privateDescription
                  End Get
                  Set(ByVal value As String)
                        privateDescription = value
                  End Set
            End Property
      End Class
 
           
In the code displayed above, I have created a LoadRSS() method which creates the WebClient object, adds the handler and initiates the request. To request a resource as a stream, you must call an OpenReadAsync method overload.
In the wc_OpenReadCompleted callback function, we check the Error property for errors. If there aren’t any, we use the XMLReader class to read the RSS xml and then load the Syndication Feed from the reader. I have also created a ‘RSSFeed’ class to store some properties of the RSS. I then use LINQ to loop through the items collection of SyndicationFeed and set the properties of the ‘RSSFeed’ class. The DataGrid is then bound to the collection.
In order to display the RSS data, I have set up each column individually in the DataGrid to format the content as required. I got some ideas of creating templates and databinding from over here.
The mark up is shown below:
        <data:DataGrid x:Name="dGrid" AutoGenerateColumns="False" IsReadOnly="True" CanUserSortColumns="True" Grid.Row="1" Grid.ColumnSpan="2">
            <data:DataGrid.Columns>
                <data:DataGridTemplateColumn>
                    <data:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <HyperlinkButton Content="{Binding Title}" NavigateUri="{Binding NavURL}" TargetName="_blank"/>
                                <local:HtmlTextBlock Text="{Binding Description}" TextWrapping="Wrap" UseLayoutRounding="True"/>
                            </StackPanel>
                        </DataTemplate>
                    </data:DataGridTemplateColumn.CellTemplate>
                </data:DataGridTemplateColumn>
            </data:DataGrid.Columns>
        </data:DataGrid>
If you noticed, I am using the HtmlTextBlock control instead of the TextBlock control since my RSS contains ‘FeedFlare’ (with HTML tags). The HtmlTextBlock control supports displaying and rendering HTML in the TextBlock and can be downloaded from here.
That’s pretty much what you require to run the application. Run the application and type in a feed URI. I am using the feed URI of dotnetcurry.com http://feeds.feedburner.com/netCurryRecentArticles
The result is as displayed below:
Silverlight RSS Reader
Cross-Domain Calls
In order to Make a Service Available Across Domain Boundaries, we require either a crossdomain.xml (supported by Flash) or the clientaccesspolicy.xml(supported by Silverlight). If these xml files are not kept in the root of the root domain, we get a 404 error.
However the best part in accessing a RSS feed hosted on FeedBurner is that the crossdomain.xml file is available on the FeedBurner domain and hence allows us to access RSS feeds. Cool!
The SyndicationFeed class makes it almost effortless to read RSS. It’s good to have a class that does the parsing automatically for us (earlier I used the XMLReader). I hope this article was useful and I thank you for viewing it. The entire source code of this article can be downloaded from here.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by srdha on Monday, May 18, 2009 6:04 AM

i gust want to say some thing "great job"

Update your Twitter randomly according to your intrest Or, from Rss Feed Or, from your own tweet message list Or, Any combination of the above three http://feedmytwitter.com
Comment posted by Rick Jackson on Tuesday, November 10, 2009 10:15 PM
Hello,

I am getting a problem while reading and displaying feeds in my listview control. I am using WebClient Class to read the xml.  I saw an example in the net that they are displaying and reading RSS feed and displaying those feed in Datagrid. Here is the link http://www.dotnetcurry.com/ShowArticle.aspx?ID=252&AspxAutoDetectCookieSupport=1 its works here :These are my original XML Links which i am converting into RSS using FeedBurner and YahooPipes :

http://www.bollywoodhungama.com/rss/news.xml

http://www.bollywoodhungama.com/rss/features.xml

http://www.bollywoodhungama.com/rss/movie_reviews.xml

http://www.bollywoodhungama.com/rss/movie_previews.xml

They are using feedburner to get the feed from this link : http://feeds.feedburner.com/netCurryRecentArticles its work perfectly. But when i insert my own feed which i hosted using feedburner i got into a big trouble my feed burner link :

http://feeds.feedburner.com/bollywoodhungama/ecog ==> Feed Burner Link

What i changed in the source [ which show is the dotnetcurry Article ] only the link  now i am getting feeds from my link then i got the error saying :

System does not support 'ISO-8859-1' encoding. Line 1, position 31.

when i used yahoo pipe link : http://pipes.yahoo.com/pipes/pipe.info?_id=a7ea3ae00656856774ea39801ea8f90 ==> Yahoo Pipe

Here i am getting System.Exception Error When i googled on this they say that clientaccesspolicy.xml need to hosted on the server.I do not have control over that. Some 1 Can u assist me where i am going wrong or something like that.

Thanks

Comment posted by Vamsi on Monday, February 8, 2010 5:52 PM
Hi -
I tried to use your example code and I am having some trouble. Hoping you would help me, here is my list of errors:

Error   1   Name 'item' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   53   17   VamsiSilverlightNavApp
Error   2   Method arguments must be enclosed in parentheses.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   53   46   VamsiSilverlightNavApp
Error   3   Name 'Description' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   53   48   VamsiSilverlightNavApp
Error   4   Name 'item' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   53   62   VamsiSilverlightNavApp
Error   5   Name 'item' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   54   17   VamsiSilverlightNavApp
Error   6   Method arguments must be enclosed in parentheses.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   54   32   VamsiSilverlightNavApp
Error   7   Name 'NavURL' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   54   34   VamsiSilverlightNavApp
Error   8   Name 'item' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   54   43   VamsiSilverlightNavApp
Error   9   Name 'Description' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   54   74   VamsiSilverlightNavApp
Error   10   Name 'item' is not declared.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   55   63   VamsiSilverlightNavApp
Error   11   End of statement expected.   C:\Users\Vamsi\Documents\Visual Studio 2008\Projects\VamsiSilverlightNavApp\VamsiSilverlightNavApp\Views\News.xaml.vb   55   78   VamsiSilverlightNavApp

Can you please help me get rid of these error's

Comment posted by DaveCS on Friday, April 15, 2011 10:53 PM
@Vamsi

The vb code is broken.
Comment posted by Jason on Wednesday, August 13, 2014 2:18 PM
Really nice write up. Helped me a lot. Thanks!