Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles
Here we explain how the new hierarchyID data type in SQL Server 2008 helps solve some of the problems in modeling and querying hierarchical information.

By Kent Tegels (September 2008)
We introduce you to the benefits of building composite applications with the Composite Application Guidance for WPF from Microsoft patterns & practices.

By Glenn Block (September 2008)
ADO.NET Data Services provide Web-accessible endpoints that allow you to filter, sort, shape, and page data without having to build that functionality yourself.

By Shawn Wildermuth (September 2008)
See how routed events and routed commands in Windows Presentation Foundation form the basis for communication between the parts of your UI.

By Brian Noyes (September 2008)
More ...
Articles by this Author
Here John Papa demonstrates how to build a Silverlight 2 user interface that communicates through WCF to interact with business entities and a database.

By John Papa (September 2008)
Here we build a solution that fits the Entity Framework into an n-tier architecture that uses WCF and WPF and the MVP pattern.

By John Papa (July 2008)
The Entity Framework is a hot topic, but how do you know when to use EntityClient, Object Services, Entity SQL, or LINQ? Find out here.

By John Papa (May 2008)
LINQ to Objects and LINQ to Entities have an arsenal of Standard Query Operators that operate on sequences to perform a wide variety of operations.

By John Papa (March 2008)
With the Entity Framework, developers are given more flexibility by being able to design around a conceptual model rather than a relational data model. To get started, you need to know how to design an Entity Data Model. John Papa walks you through that process.

By John Papa (February 2008)
This month John Papa takes a look at developing a mobile application that can access data on your application server.

By John Papa (January 2008)
WPF is one of the most important new technologies in the .NET Framework 3.0. This month John Papa introduces its data binding capabilities.

By John Papa (December 2007)
In T-SQL, views and derived tables serve similar purposes and have their advantages. But when working with SQL Server 2005,there's a third option--using Common Table Expressions (CTEs). John Papa explains.

By John Papa (October 2007)
More ...
Popular Articles
The goal of the ADO.NET Data Services Framework is to create a simple REST-based framework for exposing and consuming data-centric services easily.

By Elisa Flasko and Mike Flasko (August 2008)
One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

By Dan Griffin (May 2008)
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
More ...
Read the Blog
SQL Server 2008 supports a new data type, HierarchyID, that helps solve some of the problems in modeling and querying hier­archical information. In the September 2008 issue of MSDN Magazine, Kent Tegels introduces you to the ...
Read more!
Many people using SharePoint technologies don't realize that there is auditing support built directly into the Windows SharePoint Services (WSS) 3.0 platform. In the September 2008 issue of MSDN Magazine, Ted Pattison walks you through a ...
Read more!
The September 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Hierarchy ID: Model ...
Read more!
Silverlight 2 features a rich and robust control model that is the basis for the controls included in the platform and for third-party control packages. You can also use this control model to build controls of your own. In the August 2008 issue of MSDN Magazine, Jeff Prosise describes how to ...
Read more!
In the August 2008 issue of MSDN Magazine, Matt Milner covers several topics regarding development with Windows Workflow Foundation, some that are intended to address specific reader questions, such as how to safely share a persistence database ...
Read more!
LINQ is a powerful tool enabling quick filtering data based on a standard query language. It can tear through a structured set of data using a simple and straightforward syntax. In the August 2008 issue of MSDN Magazine, Jared Parsons demonstrates a ...
Read more!
More ...
Data Points
RSS Feeds on a Smartphone
John Papa

Code download available at: DataPoints2006_12.exe (172 KB)
Browse the Code Online
Mobile applications are a lot like other applications. They rely on data, they often communicate data over a connection, and the data needs to be managed. As mobile applications become more sophisticated, so do the tools we use for developing them. In fact, when developing data-centric mobile apps using the Microsoft® .NET Compact Framework 2.0, you rely on many of the same skills that you use to develop Windows® Forms apps. With the .NET Compact Framework, developers can use ADO.NET and other familiar libraries to manage data in a mobile device.
Developing for a Smartphone introduces yet another level of design consideration, such as accounting for the small screen size. And its built-in Internet connectivity influences application design as the ability to send and receive data lends itself to hosting applications that communicate with Web servers.
This month I will demonstrate how to build a Windows Mobile® 5.0 application that reads RSS feeds and loads them into an ADO.NET DataSet. I will start out by showing how to request an RSS feed from a URL asynchronously and then demonstrate how to read the RSS feed and load it into a DataSet. Next, I will show you how to navigate the DataSet's hierarchy to find the appropriate data containing each feed's items. Then I will discuss how to use anonymous delegates to sort the data, how to check for the existence of a field in the RSS data using ADO.NET, and how to use the WebBrowser control to navigate to a URL or display HTML. Finally, I will demonstrate how to deploy the application to a mobile device using a CAB project. The full source code for this sample application is available from the MSDN®Magazine Web site.

Preparing for Mobile Development
Developing mobile applications with the .NET Compact Framework 2.0 and Visual Studio® 2005 is very similar in many aspects to developing ASP.NET or Windows Forms applications. Before diving into the code, however, you'll need to do some setting up. Assuming you already have Visual Studio 2005 installed, you should make sure you also have the following installed, or download them as necessary from the Microsoft Web site:
Even if you are not going to use an actual Smartphone device during development and instead will rely on the emulator, you still need to install the latest version of ActiveSync®. This is used for such tasks as deploying the application to the emulator and allowing the emulator to connect to the Internet. The Windows Mobile SDK 5.0 for Smartphone adds a few project types to Visual Studio 2005 that are specific to Smartphone development. (There is also an SDK for Pocket PC development.) Finally, you should install the emulator that most closely resembles the target devices. (My application is targeting Smartphone devices with a 320×240 landscape screen.)
A word about emulators. If you have a mobile device, I highly recommend testing your application on it, rather than relying entirely on the emulator. While an emulator is a great tool, the best test is always to run the application on a physical device. When I develop a mobile application, I use the emulator but also deploy the application to a physical device at certain checkpoints to make sure everything is running smoothly in both environments.
Before running the code, you need to start the Device Emulator Manager from the Tools menu of Visual Studio. A list of available emulators will appear. Choose the 320×240 (Landscape) Windows Mobile 5.0 Smartphone Emulator. If you haven't downloaded this option, you can make do with another Windows Mobile 5.0 Smartphone emulator. The code in this column is written for a 320×240 landscape screen, but it could easily be modified to fit other resolutions.
Once you choose the emulator, right-click on it and select Connect. The emulator will then begin to boot the Smartphone. Once the Smartphone is running in the emulator, right-click the item in the Device Manager again and select Cradle. Cradling the emulator's Smartphone will allow it to talk to ActiveSync, which in turn allows it to connect to your network so it can access the Internet and grab the RSS feeds. Finally, in Visual Studio, select the 320×240 emulator from the dropdown list in the Device toolbar. This tells Visual Studio which emulator image to use when you debug and deploy.

The News Reader Application
Before diving into code, let's look at what the application does from a high level. When the application launches, it requests the RSS feeds asynchronously from their respective Web sites and loads a ListView control that provides the title of each feed and the number of items that each feed returns (see Figure 1).
Figure 1 List of RSS Feeds 
Figure 2 Feed Item List 
Figure 3 Item Description 
When you select a feed and either click the enter soft key (the middle key on the Smartphone) or choose Menu | Select, the selected feed's list of items is displayed in another form's list view, sorted with the most recent first. If the RSS feed contains the item's publication date (which is an optional element in the RSS schema), it will be displayed in the second column of the list view (see Figure 2). If there is no publication date, then the column is omitted and only the title of the item is displayed.
Once you select an item, its description is displayed in another screen. Any content within the item's description element is displayed in a WebBrowser control (see Figure 3).
The item description can contain hyperlinks or images since it reads the description element from the RSS feed. If it contains a URL, the user can click the URL and navigate to that address. If the user clicks the Select menu item with the soft key while viewing the item's description, the application switches to another screen and navigates to the URL of the selected item, loading the content into a WebBrowser control so the entire post can be viewed. The user can always navigate backwards to a previous screen by clicking the Back soft key. And from the Feed Item List screen, the user can select Done from the menu using the Left soft key to exit the application.
This application demonstrates the basic abilities you need to include in an application of this type. However, there are several features and enhancements you can include to make the app more sophisticated, such as progress bars, icons, and the ability to manage the feed list. Feel free to download the code and add your own enhancements.

Asynchronous Feed Requests
Now that I have shown how the application functions, let's take a look under the hood at the code. When the application loads, it first requests three RSS feeds (for brevity, I have hardcoded these URLs in a List<string>), looping through the registered URLs and requesting the feed for each one by calling the BeginScanFeeds method:
   List<string> urlList = new List<string>();
   urlList.Add(
     "http://msdn.microsoft.com/msdnmag/rss/        rss.aspx?Sub=Data+Points");
   urlList.Add("http://blogs.msdn.com/MainFeed.aspx");
   urlList.Add("http://blogs.technet.com/MainFeed.aspx");

   ClearList();
   foreach (string url in urlList) BeginScanFeeds(url);
 
The BeginScanFeeds method creates an instance of the HttpWebRequest class for the specified URL. The request is then made asynchronously for the given URL using the HttpWebRequest's BeginGetResponse method. This method accepts an asynchronous callback delegate (which in this case is the EndScanFeeds method) and the request:
   public void BeginScanFeeds(string url)
   {
       HttpWebRequest request = 
          (HttpWebRequest)WebRequest.Create(url);
       IAsyncResult asyncResult = request.BeginGetResponse(
           new AsyncCallback(EndScanFeeds), request);
   }
   
Each request is sent and when the response returns, the EndScanFeeds method is invoked. The EndScanFeeds method has a single argument of type IAsyncResult, which can be used to retrieve the feed. Figure 4 shows a snippet of the code from this method that puts the response from the resulting HttpWebResponse object into a string named feedData using a StreamReader object. The feedData string contains the RSS feed's XML and is passed to the LoadFeedList method, which loads the feed data into a ListView control. Because the feeds are read asynchronously and the LoadFeedList method accesses the ListView control, the method needs to be called using the Control.Invoke method.

Loading a DataSet
Once the feed has been retrieved, its contents must be parsed. While there are several ways to read an XML string, I have chosen to load the data into a DataSet, using the following code:
   DataSet ds = new DataSet();
   XmlTextReader xmlRdr = 
      new XmlTextReader(new StringReader(rssXmlData));
   ds.ReadXml(xmlRdr);
I've opted for this approach because it allows me to utilize such capabilities as checking for the existence of columns and navigating the RSS feed's hierarchy.
The feed's contents are loaded into a StringReader object, which is then used to create an XmlTextReader. The XmlTextReader can then be read by the DataSet's ReadXml method, which loads the contents of the feed into the DataSet. The RSS schema includes three main elements in the hierarchy: rss, channel, and item. (Some schemas contain more elements, such as an images element.)
The rss element is the root of the RSS feed, which contains one or more channel elements. The channel elements represent the feed and can contain a series of child elements that describe the feed (such as title, link, description, and item). The item element is a required child of the channel element. (This, by the way, is not the same as the main item element.) Item elements represent each item in the feed. For example, in the MSDN Blog, the channel is the MSDN Blog while the items represent the posts.
When an RSS feed is loaded into a DataSet, the main elements-rss, channel, and item-are loaded as tables. Each level of the hierarchy becomes a DataTable and can be read and navigated using the DataTable's features. The simple child elements that describe each main element are loaded as columns in the respective DataTable. For example, the channel DataTable contains a DataColumn for the item, description, and link elements (all three of these elements are required).
Finally, a DataRelation is created between the channel DataTable and the item DataTable representing how a channel contains zero or more items. I exploit this relationship so the application can locate a specific channel's items when a user selects a specific feed.

Loading the List of Feeds
Once the feed is loaded into a DataSet, I locate the channel table and grab the channel's title and the number of items contained in each channel. I store this information in an array and load it into the list view as the feeds are received (see Figure 5).
The title of the channel is accessed using the standard ADO.NET syntax to read the value from a DataRow's column. To get the total number of items in each channel I use the DataRow's GetChildRows method to return an array of DataRow objects for the current channel row's items. The GetChildRows method accepts the name of the DataRelation, which by default is the concatenation of the channel DataTable's name and the item DataTable's name, with an underscore between them. Notice that I store a reference to the channel's DataRow in the tag of the ListViewItem. This makes it easy to grab the feed's information when a user selects a particular feed.

Sorting with Anonymous Delegates
When a user selects a feed, the DataRow is passed to the FeedItemList form, which then loads the list of items into a ListView control. I load the title of the item as well as the publication date, if it is provided. Since the pubDate element is not a required element of the RSS 2.0 schema, I first check to see if the column exists in the item DataTable. Since I have an array of DataRow objects that represent the feed's items, I can use that to find the DataRows' DataTable object and then use the DataTable.Columns.Contains method to check whether the pubDate column exists. It may sound like a lot to do, but the code is quite simple, as shown here:
bool containsPubDate = (itemRows[0].Table.Columns.Contains("pubDate"));
Once I determine whether the pubDate exists, I can then determine how to sort and display the items in the list view. If the pubDate exists, I sort the items by date in descending order. If there is no pubDate, I sort the items by title and hide the publication date column in the list view.
The following code executes if the pubDate exists:
colNewsItemName.Width = 170;
colPubDate.Width = 140;

Array.Sort(itemRows, delegate(DataRow row1, DataRow row2)
{
    DateTime pubDate1 = ParseDateTime(row1["pubDate"].ToString());
    DateTime pubDate2 = ParseDateTime(row2["pubDate"].ToString());
    return pubDate2.CompareTo(pubDate1);
});
It sets the width of the columns so the app will display both the item's title and publication date. It then uses the Array.Sort method to sort the array of DataRow objects. Before I can sort the dates, I have to convert them to a valid DateTime. Once this conversion is done I use a custom comparer delegate to sort the DataRow array.
The custom comparer delegate is a nice, short way to code the sorting routine. I could have created an explicit routine to handle the sorting, but since I wanted to minimize the lines of code, the custom comparer delegate was a good option. The comparison of the dates is executed for each element comparison in the array. In this example I create an anonymous delegate that accepts two DataRow objects and compares them by evaluating the values in their pubDate columns.
If the pubDate column does not exist, I hide the second column in the list view and expand the first column to fill the screen width. Then I sort the DataRow array by the item title in ascending order. I use the same technique in this case, except this time I compare string values:
colNewsItemName.Width = 310;
colPubDate.Width = 0;

Array.Sort(itemRows, delegate(DataRow row1, DataRow row2)
{
    return row1["title"].ToString().CompareTo(row2["title"].ToString());
});
The anonymous method provides a great way to help reduce code when you do not need to reuse the comparer functionality.
Once the DataRow array is sorted, I loop through the items and grab the title and the pubDate (if it exists), as shown in Figure 6. If the pubDate exists, I format it accordingly and load the title and pubDate into a string array, which I then use to load the list view. At this point, the list looks like the one shown in Figure 2.

Displaying with the WebBrowser Control
When the user selects an item, the selected ListViewItem is examined and the DataRow of the selected item is retrieved from its Tag property. The DataRow that contains the selected item is passed to the constructor for the ItemSummary form, which displays the description of the selected item. Note that I did not use a label control to display the description because the descriptions of an item in an RSS feed often contains embedded HTML. Thus I used the WebBrowser control to display the description.
Figure 3 shows the summary of an item's description in the WebBrowser control. You can see that the summary description includes hyperlinks and other HTML elements. To render the HTML, I set the WebBrowser control's DocumentText property to the item's description and the Form's Text property to the title of the item:
this.Text = itemRow["title"].ToString();
webSummary.DocumentText = itemRow["description"].ToString();
In this application, the WebBrowser control serves two purposes. It is used by the ItemSummary form to display the description of the item, which may or may not contain HTML. It is also used by the Item form, which navigates to the link specified in the item's DataRow. This is the more conventional way to use the WebBrowser control:
this.Text = itemRow["title"].ToString();
webItem.Navigate(new Uri(itemRow["link"].ToString()));
Here, I have set the title of the Item form to the item's title, and I navigate to the item's URL in the WebBrowser control using the Navigate method. The link is then located and the page is loaded into the WebBrowser control.

Deploying to a Smartphone
Once the application is built, it is time to deploy it to an actual Smartphone device. At this point, I usually shut down the emulator window and the Device Emulator Manager so I can fully test the deployment to a Smartphone.
Some notes about deploying the application. First, you should create a Smartphone Device CAB project and add it to the current solution. Also, to run an application built using the .NET Compact Framework 2.0, the Framework must be installed on the mobile device. Once these two steps have been taken care of, you can copy the CAB file to the mobile device and install the application directly.
I created the CAB project, named MSDN200611, and added content files and primary output. The content files pick up the icon file I used in the Smartphone device application. I created a shortcut to the primary output, added the Start Menu folder to the CAB file project, and dragged the shortcut to the Start Menu folder-this puts the application in the Smartphone's list of applications in its Start Menu. I also renamed the shortcut to a friendlier and shorter name.

Conclusion
When developing datacentric mobile applications with the .NET Compact Framework 2.0, you'll use many of the same skills that you use to develop Windows Forms applications. This month, I have demonstrated how ADO.NET can be used to load RSS feeds, navigate the feeds and their items, and check for the existence of RSS information. Anonymous methods and asynchronous invocation assist in the development, but the core of the application is still the data itself-whether it be the RSS feed, the DataSet, an array of DataRow objects, or the HTML that is rendered in the WebBrowser control for the item description.

Send your questions and comments for John to  mmdata@microsoft.com.


John Papa is a senior .NET Consultant with ASPSOFT (aspsoft.com) and a baseball fanatic who spends most of his summer nights rooting for the Yankees with his family and his faithful dog, Kadi. John, a C# MVP, has authored several books on ADO, XML, and SQL Server, and can often be found speaking at industry conferences such as VSLive or blogging at codebetter.com/blogs/john.papa.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker