Annsa - Useful Code Resources

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.