Following is a utility class I wrote to help me read RSS items asynchronously on a Silverlight for Windows Phone 7 application.
I will present how it was written and then how to use it. At the end of this post, you can find a sample application that contains all the code.
How to Read RSS?
Add Helper Assembly
The first thing we need to do is to add a reference to the assembly, System.ServiceModel.Syndication.dll which contains classes that can parse RSS feeds.
This assembly is part of the Silverlight 3 SDK. It isn’t part of the Windows Phone 7 SDK, but there is no problem in using it there. You can find the file under %ProgramFiles%\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.ServiceModel.Syndication.dll.
You will get the following warning, just ignore it, it works.
Define RssItem
Before we get to business, let’s define a model class that will encapsulate the data of a single RSS item.
Our RssItem
class will hold the following properties: Title
, Summary
, PublishedDate
and Url
. In addition, I provide a PlainSummary
property that will hold a plain text version of the RSS item. Usually, the summary has HTML tags that we just want to ignore, thus PlainSummary
for the rescue.
public class RssItem
{
public RssItem(string title, string summary, string publishedDate, string url)
{
Title = title;
Summary = summary;
PublishedDate = publishedDate;
Url = url;
PlainSummary = HttpUtility.HtmlDecode(Regex.Replace(summary, "<[^>]+?>", ""));
}
public string Title { get; set; }
public string Summary { get; set; }
public string PublishedDate { get; set; }
public string Url { get; set; }
public string PlainSummary { get; set; }
}
Implement the RSS Service
The RSS service will get the RSS feed URL as a parameter. In addition, since we want our class to work asynchronously, we will accept as parameters a few more delegates:
Action<IEnumerable<RssItem>> onGetRssItemsCompleted
, which will be called when the RSS items are ready to be processed.
Action<Exception> onError
, which will be called if there is an error while getting the RSS items.
Action onFinally
, which will be called always, whether there was an exception or not. Think of it as the finally
section of a common try
-catch
block.
So the method signature will be:
public static void GetRssItems(string rssFeed,
Action<IEnumerable<RssItem>> onGetRssItemsCompleted = null,
Action<Exception> onError = null, Action onFinally = null)
To get the feed XML, we will use the WebClient class:
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += delegate(object sender, OpenReadCompletedEventArgs e)
{
...
};
webClient.OpenReadAsync(new Uri(rssFeed));
The actual RSS parsing is done using the SyndicationFeed class from our helper assembly:
List<RssItem> rssItems = new List<RssItem>();
Stream stream = e.Result;
XmlReader response = XmlReader.Create(stream);
SyndicationFeed feeds = SyndicationFeed.Load(response);
foreach (SyndicationItem f in feeds.Items)
{
RssItem rssItem = new RssItem(f.Title.Text, f.Summary.Text, f.PublishDate.ToString(),
f.Links[0].Uri.AbsoluteUri);
rssItems.Add(rssItem);
}
The rest of the code is for handling the different delegates: onCompleted
, onError
and onFinally
. I bring here the full method:
public static void GetRssItems(string rssFeed,
Action<IEnumerable<RssItem>> onGetRssItemsCompleted = null,
Action<Exception> onError = null, Action onFinally = null)
{
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += delegate(object sender, OpenReadCompletedEventArgs e)
{
try
{
if (e.Error != null)
{
if (onError != null)
{
onError(e.Error);
}
return;
}
List<RssItem> rssItems = new List<RssItem>();
Stream stream = e.Result;
XmlReader response = XmlReader.Create(stream);
SyndicationFeed feeds = SyndicationFeed.Load(response);
foreach (SyndicationItem f in feeds.Items)
{
RssItem rssItem = new RssItem(f.Title.Text, f.Summary.Text,
f.PublishDate.ToString(), f.Links[0].Uri.AbsoluteUri);
rssItems.Add(rssItem);
}
if (onGetRssItemsCompleted != null)
{
onGetRssItemsCompleted(rssItems);
}
}
finally
{
if (onFinally != null)
{
onFinally();
}
}
};
webClient.OpenReadAsync(new Uri(rssFeed));
}
Using the RSS Service
Using the class is very easy, just provide the URL as the first parameter and a delegate for getting the “completed” notification.
private void Button_Click(object sender, RoutedEventArgs e)
{
RssService.GetRssItems(
WindowsPhoneBlogPosts,
(items) => { listbox.ItemsSource = items; },
(exception) => { MessageBox.Show(exception.Message); },
null
);
}
There is a sample application which can be downloaded here.
Note: This code was first published as part of the “Using Pivot and Panorama Controls” lab found in the Windows Phone Training Kit for Developers, which I wrote for Microsoft.
That’s it for now,
Arik Poznanski