December 2010

Volume 25 Number 12

Windows Phone 7 Apps - Build Data-Driven Apps with Microsoft Azure and Windows Phone 7

By Danilo Diaz | December 2010

In the last 30 years, we’ve seen an explosion in the computer hardware industry. From mainframes to desktop computers to handheld devices, the hardware keeps getting more powerful even as it shrinks. Developers have, to some extent, become a bit spoiled by this constant increase in computing power and now expect limitless computer resources on every device for which they write applications. Many younger developers have no memory of a time when the size and efficiency of your code were important factors.

The latest trend in development is in embracing the rise in popularity of smartphones. When coding for smartphone devices, many developers have to adjust to the fact that, although today’s phones are extremely powerful compared to devices of just a few years ago, they do face limitations. These limitations are related to size, processor power, memory and connectivity. You need to understand how to work around these limitations when creating mobile applications to ensure good performance and the best user experience.

Some of the reasons for less-than-optimal app performance can be attributed directly to poor design decisions by the developer. However, in other cases, some of these factors are not directly in the control of the developer. A poorly performing application could be a symptom of a slow or offline third-party service, dropped mobile broadband connections or the nature of the data you’re working with (such as streaming media files or large sets of data).

Whatever the cause might be, the performance perceived by the end user of your application must be one of the top concerns of any software developer. In this article, we’ll cover some high-level considerations for designing robust, data-driven Windows Phone 7 applications in a way that can provide a great user experience and scale gracefully.

Let’s first take a moment and set up a scenario within which we can examine some design and coding choices. As an example, we’re going to work with a fictitious travel information application that provides information about user-selected airline flights. As shown in Figure 1, the main screen of the application shows a number of data elements including current weather and flight status. You can see that, as applications become more expressive and data-centric, developing them becomes a bit more challenging. There are simply more areas where your code can fall short.

image: The Flight Information Sample App

Figure 1 The Flight Information Sample App

UI Thread Blocking

Let’s start by looking at the UI. It’s easy to get the pattern wrong by designing the app as if you’re coding for the desktop, so let’s take a look at some phone-specific UI issues.

When an application doesn’t respond as expected to user commands, the effect on the overall user experience can be dramatic. Slow response to swipe, tap or pinch can be detrimental to the overall appeal of the app. However, these are pretty simple issues to anticipate and address, as you’ll see.

Consider a ListBox. When an ItemTemplate contains images or is loading data from a feed, there’s a very good chance the UI thread will be blocked and the UI will pause until the requests or calculations complete. Therefore, as you develop the UI, one approach is to perform long calculations—including WebRequests—off of the UI thread. In fact, this is a good approach for any app, mobile or not.

Another issue that may create performance problems is when you’re binding lots of items to the ItemSource without throttling injection into the ListBox control. A better approach would be to bind an ObservableCollection and populate a few items into the collection every 20-30 ms. This unlocks the UI thread to be responsive to the user.

In the case of our sample app, we’re also making heavy use of images on the screen. The ListBox needs to actually download the image in order to display that data. While this seems OK, doing this work on the UI thread would block the user from any gesture input. Loading images on a background thread solves a number of problems both in terms of memory requirements and freeing up the UI thread, while at the same time making the application faster.

Everything that we display to the user must be rendered. Rendering requires layout, alignment and calculation to display correctly. As more layers are added to the UI, the calculation and overall rendering costs increase. Although Silverlight already virtualizes the UI, it doesn’t virtualize the data that’s being bound. This means that if we were to bind 10,000 items to our ListBox, Silverlight would instantiate all 10,000 ListItems before they were rendered.

Be aware of what you’re data-binding and keep the bound set as small as possible. If you need to handle large sets of data-bind items, consider dynamically handling the rendering behind the scenes. This is true of desktop apps as well, of course—the impact of these choices is just amplified on a phone.

ValueConverters may have a drastic impact on rendering performance because they’re defined using custom code and rendering cannot be pre-determined and cached ahead of actual element rendering and layout.

Dealing with Data

Next, we need to talk about data storage in Windows Phone 7. Let’s just get straight to the point: There’s no relational database engine available to developers. SQL Server Compact (SQL CE) is installed with the Windows Phone 7 OS, but currently there’s no API available to developers. So creating a database to store application data—in our example, trip information—isn’t going to work.

That said, there’s a wide range of options for getting data to and from our application. A common approach is to use a cloud service such as Azure for data persistence. There are many technologies available for building the service layer of your application, REST and SOAP being the most popular. SOAP is the first choice for many developers, but we think REST provides a more efficient and simpler-to-implement method of making data requests.

We employ a few methods that provide data to the application and that we can access by using REST expressions such as these:

/Trip/Create/PHL-BOS-SEA/xxxx/2010-04-10
/Flight/CheckStatus/US743

REST enables us to use either XML or JSON for a message format.

From the Web front-end perspective, we chose the ASP.NET MVC framework (asp.net/mvc) because it allows us to process the request and return any type of markup using a custom view.

Our sample application needs to handle both trip and flight information, so we create a FlightController and a TripController that intercept requests for this information:

// GET: /Flight/CheckStatus/US743
public ActionResult CheckStatusByFlight(
  string flightNumber) {
  return CheckStatus(flightNumber, DateTime.Now);
}
// GET: /Flight/RegisterInterest/US743/2010-04-12
public ActionResult CheckStatus(
  string flightNumber, DateTime date) {
  Flight f = new Flight(flightNumber, date);
  GetFlightStatus(f);
  return new XmlResultView<Flight>(f);
}

To provide simplified access methods and save a few bytes of bandwidth, if the date is today we might design a shortcut method for getting this data without implicitly specifying today’s date.

Cached and Persistent Data

The flight status service is an element in our application that’s not in our control and thus will be part of the performance puzzle. Because successful application may receive a considerable number of requests, it’s important to think about a caching strategy.

Typically, the closer the flight is to departure, the higher the number of requests for its information can be expected. Higher numbers of near-concurrent requests can affect not only the performance of the application, but also the costs associated with storing and manipulating the data. As a general rule, Azure applications accrue bandwidth charges both on request and return, and flight information services could also incur access charges. The amount of data returned will need to be no more than what’s needed by the application.

Microsoft Azure provides a wide range of options for data storage—from tables, blobs and queues to relational database-like storage via SQL Azure. We decided to use SQL Azure because it uses familiar SQL Server programming techniques and enables us to easily store and access both cached flight data and persistent trip information.

Figure 2 shows the simple storage layer we designed using the Entity Framework.

image: Flight Data Storage Schema

Figure 2 Flight Data Storage Schema

Returning Data

We return data to the client via our custom view. Because we’re using ASP.NET MVC, each view needs to derive from ActionResult and implement ExecuteResult.

As mentioned earlier, we can provide either XML or JSON representations of the flight information via our REST service. Let’s take a look at the XML option first. The serializer to produce XML requires a type, so we create a Generics class as shown in Figure 3.

Figure 3 Serializing XML

public class XmlResultView<T> : ActionResult {
  object _model = null;
  public XmlResultView(object model) {
    this._model = model;
  }
  public override void ExecuteResult(ControllerContext context) {
    // Create where to write 
    MemoryStream mem = new MemoryStream();
    // Pack characters as compact as possible, 
    // remove the decl, do not indent.
    XmlWriterSettings settings = new XmlWriterSettings() { 
      Encoding = System.Text.Encoding.UTF8, 
      Indent = false, OmitXmlDeclaration = true };
    XmlWriter writer = XmlTextWriter.Create(mem, settings);
    
    // Create a type serializer
    XmlSerializer ser = new XmlSerializer(typeof(T));
    // Write the model to the stream
    ser.Serialize(writer, _model);
    context.HttpContext.Response.OutputStream.Write(
      mem.ToArray(), 0, (int)mem.Length);
  }
}

We could just as easily work with JSON for our data. The only element of our solution that would change would be the contents of the ExecuteResult method. Using JsonResult, we can produce the JSON return from our service in just a few lines of code:

// Create the serializer
var result = new JsonResult();
// Enable the requests that originate from an HTTP GET
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
// Set data to return
result.Data = _model;
// Write the data to the stream
result.ExecuteResult(context);

What about saving data to the actual device? It wouldn’t make sense to force the application to pull data from the service every time the user needs access to trip information. Although there’s no relational data store in Windows Phone 7, developers do have access to a feature called Isolated Storage. This works just like Silverlight 4 Isolated Storage, but without a size limit.

There are two main methods you need to save and retrieve data on the phone: SaveData and GetSavedData. Examples showing how we’d use these for the flight information app are shown in Figure 4.

Figure 4 Saving and Retrieving Local Data

public static IEnumerable<Trips> GetSavedData() {
  IEnumerable<Trips> trips = new List<Trips>();
  try {
    using (var store = 
      IsolatedStorageFile.GetUserStoreForApplication()) {
      string offlineData = 
        Path.Combine("TravelBuddy", "Offline");
      string offlineDataFile = 
        Path.Combine(offlineData, "offline.xml");
      IsolatedStorageFileStream dataFile = null;
      if (store.FileExists(offlineDataFile)) {
        dataFile = 
          store.OpenFile(offlineDataFile, FileMode.Open);
        DataContractSerializer ser = 
          new DataContractSerializer(
          typeof(IEnumerable<Trips>));
        // Deserialize the data and read it 
        trips = 
          (IEnumerable<Trips>)ser.ReadObject(dataFile);
        dataFile.Close();
      }
      else
        MessageBox.Show("No data available");
    }
  }
  catch (IsolatedStorageException) {
    // Fail gracefully
  }
  return trips;
}
public static void SaveOfflineData(IEnumerable<Trips> trip) {
  try {
    using (var store = 
      IsolatedStorageFile.GetUserStoreForApplication()) {
      // Create three directories in the root.
      store.CreateDirectory("TravelBuddy");
      // Create three subdirectories under MyApp1.
      string offlineData = 
        Path.Combine("TravelBuddy", "Offline");
      if (!store.DirectoryExists(offlineData))
        store.CreateDirectory(offlineData);
      string offlineDataFile = 
        Path.Combine(offlineData, "offline.xml");
      IsolatedStorageFileStream dataFile = 
        dataFile = store.OpenFile(offlineDataFile, 
        FileMode.OpenOrCreate);
      DataContractSerializer ser =
        new DataContractSerializer(typeof(IEnumerable<Trip>));
      ser.WriteObject(dataFile, trip);
                   
      dataFile.Close();
    }
  }
  catch (IsolatedStorageException) {
    // Fail gracefully
  }
}

Dealing with Network Failures

The networks used by mobile devices can have widely variable connectivity—sometimes becoming completely unavailable due to location, congestion or even users disconnecting manually (in the case of airplane mode, for instance). You have to accept this as a fact of life. As mobile application developers we must take this into consideration when building applications.

Another type of network failure is service layer failure. Many mobile applications consume data from third-party services. These services may not come with service-level agreements, which leaves your application at the mercy of the provider. In other words, it’s out of your control, and you have to be prepared to deal with outages.

Regardless of the source of the network failure, you still need to provide the best user experience possible. You need to provide some level of functionality in the event of any type of network failure. For our flight status application this means that we want to allow the user to access as much information as possible even if network connectivity is lost from either the server or the client side.

There are numerous ways to achieve this. For now, we’ll concentrate on three simple ways in which you could accomplish this: get the data while you can, cache data locally and cache data on a server you control.

Using Push Notifications

When the user enters trip information into the application, the information will be uploaded to a cloud service. The service will then keep polling the various services that provide its flight and weather data. It also looks for changes in the data over time, such as a flight status change or an airport that reports a delay.

When a change is found, you want to get that information to the user as promptly and efficiently as possible. One way to do that is for the service to push the information to the client app. This will provide the user access to the most current set of available data the moment the data becomes available. Because the data was pushed to the client, the data is available even if the user loses his network connection.

We can accomplish this with our Azure Service by using Windows Phone Push Notification. The Windows Phone Push Notification feature is made up of three components: monitor services, the Microsoft Push Notification Service and a message handling method.

A monitor service is a cloud service that constantly looks for new information for our application. We’ll discuss this in more detail later.

The Push Notification Service is part of the Microsoft hosted services that are used to relay messages to Windows Phone 7 devices. This service is available to all Windows Phone 7 app developers.

The message handler method does what its name suggests: It simply receives messages from the Push Notification Service.

There are three default notification types in Windows Phone 7: Tile, Push and Toast notifications. Notifications are an important part of the user experience and you need to consider their use carefully. Repetitive or intrusive notifications can degrade performance of your application and others running on the device. They can also annoy users. Consider the frequency at which notifications are sent and the types of events that you want to get the attention of users.

In Windows Phone 7, notifications are delivered via batching, so the transaction may not be instant. The timeliness of the notification is not guaranteed and the decision on how to deliver the notification to the client is handled by the service; the service does its best to determine how quickly it can deliver the message to the phone.

The workflow for push notifications is:

  1. Client app requests a channel connection to the Push Notification Service.
  2. The Push Notification Service responds with the channel URI.
  3. The client app sends a message to the monitoring service with the Push Notification Service channel URI as well as a payload.
  4. When the monitoring service detects a change of information (flight cancellations, flight delays or weather alerts in our sample app) it ends a message to the Push Notification Service.
  5. The Push Notification Service relays the message to the Windows Phone 7 device.
  6. The message handler processes the message on the device.

Caching Data Locally

Another way to make data available to your app is to cache it locally so there’s always some data in the UI. Then you can use other means in the background to update the local data (if possible). The upside of this method is that the application can load and be usable quickly even if updating information has to occur asynchronously behind the scenes.

In a nutshell, you use Isolated Storage to save the most recent set of data. When the application opens, it immediately grabs any data available in local Isolated Storage and renders it. In the meantime, the application calls the Azure Service for updated information. If new information is found, it’s serialized and transferred to the device, Isolated Storage gets updated, and you render the UI again with updated information. For a better user experience, you probably want to indicate in the UI what time and date the information was refreshed.

On a side note, if the application is using the Model-View-ViewModel (MVVM) design pattern, the update to the UI can happen automatically via Silverlight data-binding features. For more information on MVVM and Silverlight, see Robert McCarter’s article, “Problems and Solutions with Model-View-ViewModel,” at msdn.microsoft.com/magazine/ff798279.

Caching Data on Your Server

There’s a middle ground between pushing data directly to your app as it becomes available and storing data on the device: grabbing data from third-party services and caching it in your cloud app until the Windows Phone 7 app requests it.

This technique requires a new layer of abstraction in your application. In essence, the goal here is to remove the dependency of a third-party service from your application. Your service pulls and caches the data for any third-party service dependencies. If the third-party service goes down, you’ll at least have some data in the cache that you can provide to the application on devices.

A service like this could be easily cloned or extended to pull the data from various services, thus reducing your dependency on any one vendor or data source, which makes changing vendors a lot easier.

For more information about setting up data-focused solutions in Azure, see “Fueling Your Application’s Engine with Microsoft Azure Storage” by Kevin Hoffman and Nathan Dudek (msdn.microsoft.com/magazine/ee335721). In addition, although not directly focused on Windows Phone 7 scenarios, Paul Stubb’s article, “Create a Silverlight 4 Web Part for SharePoint 2010,” is good reading on data-bound design for Silverlight and Web services (msdn.microsoft.com/magazine/ff956224).

Monitoring Service

As mentioned earlier, the notification feature is an important part of our flight status application. This feature is actually composed of several different services within the application. Perhaps most important to the usefulness of the app, the monitoring service periodically polls third-party data services and relays information like flight delays, airport delays and weather alerts back to the device.

In our application, the monitoring service reads the current list of flights and airport codes and uses this information to collect relevant data. This information is then stored back in the SQL Azure database as a cache entry so that it can be retrieved by the /Flight/CheckStatus service shown earlier. Our monitoring service is implemented with an Azure Worker Role. The main goal on this Worker Role is to pull status information on flight delays and airport status for every user’s flight collection. The frequency of the update pull increases as it approaches the scheduled flight departure time.

For some ideas about how you could implement such a service, read Joseph Fultz’s blog post, “Migrating Windows Service to Azure Worker Role: Image Conversion Example Using Storage” (bit.ly/aKY8iv).

Putting It All Together

Hopefully we’ve given you a broad overview of the issues you need to consider when designing a data-driven Windows Phone 7 application. UI responsiveness, as well as time access to your data sources, play into making a great user experience for your app.

To dig a bit deeper, start with Joshua Partlow’s article, “Getting Started with Windows Phone Development Tools” (msdn.microsoft.com/magazine/gg232764). You’ll also want to see the article, “Developing and Deploying Microsoft Azure Apps in Visual Studio 2010,” by Jim Nakashima, Hani Atassi and Danny Thorpe (msdn.microsoft.com/magazine/ee336122).

To put your Azure and Windows Phone 7 development together, take a look at Ramon Arjona’s article, “Windows Phone and the Cloud—an Introduction” (msdn.microsoft.com/magazine/ff872395).


Danilo Diaz is a developer evangelist for the Microsoft Mid-Atlantic State district. In this role, he helps developers understand Microsoft product offerings and strategy.

Max Zilberman is an architect evangelist in the NYC and Mid-Atlantic States districts. Prior to joining Microsoft, Zilberman held various senior technical positions at a top-tier health insurer.

Thanks to the following technical expert for reviewing this article: Ramon Arjona