Consuming an RSS Feed in Silverlight with .Net 3.5 SyndicationFeed, Part 2
In Part 1
we introduced a Silverlight control designed to present
an RSS feed. In this part, we'll discuss the initialisation of the control
and suggest an alternative databinding approach.
Initialisation
To allow our Silverlight control to be as flexible as possible, the URL of the
RSS Feed and the number of items to be displayed can be configured "externally"
by the host page. Silverlight supports this feature through initialisation
parameters, a crude name/value pair listing.
The ASP Silverlight control supports an InitParameters attribute through which
the name/value pairs can be set, as shown below.
<asp:Silverlight ID="Xaml1"
runat="server"
Source="~/ClientBin/RSSFeedSample.xap"
MinimumVersion="2.0.30523"
Width="200"
Height="600"
InitParameters="FeedUrl=http://feeds.feedburner.com/blogspot/MKuf,FeedItemCount=6"/>
The Silverlight control can then retrieve any initialisation parameters
in its Application_Startup event handler and process them as approriate.
In our sample we use the values to set relevant properties on
our Silverlight control.
private void Application_Startup(object sender, StartupEventArgs e)
{
RssFeedWithConverters rssFeedControl = new RssFeedWithConverters();
// Set properties based on any startup parameters
if ( e.InitParams.ContainsKey(_feedUrlKey) )
{
rssFeedControl.FeedUrl = e.InitParams[_feedUrlKey];
}
if ( e.InitParams.ContainsKey(_feedItemCountKey) )
{
rssFeedControl.FeedItemCount = System.Convert.ToInt32(e.InitParams[_feedItemCountKey]);
}
...
}
Databinding without Converters
As mentioned in
Part 1, the Converters used to support Silverlight databinding are
cumbersome. As discussed, they provide a translation mechanism from one type
to another (the binding can be one or two way).
As an alternative approach, the Silverlight control could be bound to a
class that provides properties for all the elements required. So rather than
writing a converter to get the first Uri from the Links property
of the SyndicationItem class, we could derive a class from SyndicationItem
that supported a FirstLink property that the Silverlight control
could bind to directly.
This approach offers a cleaner databinding interface between the Silverlight
control and the source object. It's also an approach which is easier to test.
Creating the derived class is straightforward, as is providing the read only
properties needed for our sample.
/// <summary>
/// SyndicationItemEx derives from SyndicationItem and provides
/// a number of useful additional properties (used for
/// databinding)
/// </summary>
public class SyndicationItemEx : SyndicationItem
{
private const int maxEntryTextSize = 100;
/// <summary>
/// Constructor
/// </summary>
public SyndicationItemEx(SyndicationItem source) : base(source)
{
}
/// <summary>
/// Returns the first link in the "Links" collection
/// </summary>
public Uri FirstLink
{
get { return this.Links.First().Uri; }
}
...
}
List manipulation with LINQ
With the derived class created, we need to convert the list returned by the
SyndicationFeed object from a list of SyndicationItem objects to a
list of our newly create SyndicationItemEx objects. We can then use this list of
our derived objects to bind to the Silverlight ItemsControl
With LINQ we can perform this conversion operation quickly and simply;
/// <summary>
/// Called when the feed contents have been downloaded.
/// Extracts the contents using SyndicationFeed. Converts
/// the list to a list of the derived SyndicationFeedEx type and
/// binds the results to the Silverlight Items control
/// </summary>
void FeedDownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Result))
{
XmlReader feedReader = XmlReader.Create(new StringReader(e.Result));
SyndicationFeed feed = SyndicationFeed.Load(feedReader);
rssList.ItemsSource = feed.Items
.Select(x => new SyndicationItemEx(x))
.ToList<SyndicationItemEx>()
.Take(this.FeedItemCount);
}
}
You can view the XAML for this revised Silverlight control
here
and the associated code-behind
here.
Silverlight Gotchas - MIME Type
Should you decide to download and try this sample code, you may encounter
problems downloading the Silverlight control to the client browser. To successfully
download a Silverlight Control (which is simply a ZIP file with a ".XAP" extension) the
server hosting the file, must have the necessary Silverlight MIME type defined.
You can learn more about this configuration setting here.
Silverlight Gotchas - Cross Domain Access
It is worth noting that Silverlight enforces some restrictions
on cross domain access. These restrictions will apply to the download of feed content
using the WebClient object as we do in this example. When Silverlight attempts to
access content on a different host, it requires that the remote host includes a policy file
that permits access to the service on that host.
Silverlight will attempt to access a file named clientaccesspolicy.xml on the root of
the remote server and, failing that, will attempt to access a file named crossdomain.xml
(which is used by Adobe Flash). If neither of these files is present the download
or service call will fail - and usually with no error reported.
Tim Heuer has a great video describing cross domain policy files here
here
and a useful post on his blog
here.
Summary
Hopefully this sample has given a quick insight into some of
the features of the .Net 3.5 Framework and working with
Silverlight. The .Net 3.5 Framework offers a significant expansion
over the previous framework with LINQ in particular introducing some
incredibly powerful functionality. Silverlight means .Net developers
have a route to cross-platform delivery previously only available through
tools like Adobe Flash.