June 2009

Volume 24 Number 06

Data Points

Data Points - Building An Out-of-Browser Client With Silverlight 3

By John Papa | June 2009

This article is based on prerelease versions of Silverlight 3 and Expression Blend.

Code download available

Contents

Eyes On TheTarget
Install To Desktop
Manifest Essentials
Running Offline
Network Connectivity
Storing Data Offline

Silverlight 3 applications are no longer restricted to running in a browser. They can be run in a browser or it they can be detached from the browser and run from the desktop. These out-of-browser applications allow you to bring the richness of Silverlight 3 applications directly to the desktop without the restriction of running within a browser.

In this month's column, I'll discuss how to build a data-driven standalone Silverlight 3 application. I'll begin by demonstrating an overview of the sample application. Next, I'll outline the steps needed to take the application and make it work outside the browser. Being out of the browser requires some additional features such as an ability to detect connectivity. I'll discuss how to detect the status of the offline application and how to handle storing data offline when the network connectivity is interrupted. Other features I'll discuss along the way are building icons into the out-of-browser application, using Isolated Storage to store data on the client computer, showing the status of the out-of-browser application, and handling state change events. The sample application is a lightweight version of a Twitter-like client that sends and retrieves messages from the Twitter servers. All examples are included in this month's code download.

Eyes On TheTarget

Before diving into the out-of-browser features, it is important to understand what features I'll use to build the sample application in this article, so let's begin with an overview. The sample application demonstrates how to build a data-driven application with Silverlight 3 and its out-of-browser features. The goal of the sample application is to create a Twitter client that allows sending of new messages and retrieval of a user's friend timeline, replies, and direct messages. It is a simple, lightweight version of a Twitter client, though many more features could be added following the models I'll discuss here. Figure 1shows the sample application running out of the browser.

fig01.gif

Figure 1 Silverlight Twitter Client at a Glance

The SilverTwit application will request and show the messages from everyone the user is following when the Home button is clicked. When the Replies and Direct buttons are clicked, the replies to the logged-in user and the direct messages to the logged-in user are retrieved and displayed, respectively. The request for the messages is made from the Silverlight out-of-browser application to a Web service (also included in the sample project) and then the Web service relays the requests to the public Twitter API. This relay through a third-party service is required because Twitter does not allow cross-domain communication to be made from a Web client to Twitter directly. However, Twitter does allow calls made from server applications such as the one used in the sample solution. Other alternatives are to use PopFly or Yahoo Pipes to relay the requests.

For more information on cross-domain policies, please refer to my September 2008 Data Points column. In that column, I discuss the file formats and how the policies work.

When a user enters a message and clicks the Post button, the message is sent by way of the relay Web service on to Twitter. If the application cannot detect a network connection and a user tries to post a message, the message will be stored locally until a network connection can be restored. At that time the deferred message will be sent to Twitter.

Notice that the chrome around the sample application shown in Figure 1contains the application icon, the application's title, and the standard minimize, maximize, and close icons. The title and icons used for the window, the desktop, and other aspects of the application can be customized when you're building the application in Visual Studio or Expression Blend. This window is launched using the sllauncher.exe process and its host the Silverlight 3 out-of-browser application.

The bottom of the SilverTwit sample application contains statistics on whether a network connection is detected or not, if the application is running in or out of a browser, and whether the application has been detached. These features all help the out-of-browser application identify how it should operate. For example, if a network connection is not detected, there is no reason to look for new messages or send new messages to Twitter. When in this disconnected network state, the application must react accordingly. A Detach button also exists in the lower section of the application that will detach the application to run outside of the browser.

Install To Desktop

Silverlight 2 applications are restricted to running inside a browser. However Silverlight 3 applications can run inside the browser or out. The process of taking the application out of the browser is known as "detaching." Once the Silverlight 3 application has been detached, it can be run from the Start menu or from a desktop icon. Out-of-browser applications run on the desktop inside a window that is hosted from the sllauncher.exe process. The out-of-browser applications can still access the network and use all of the .NET framework libraries available to Silverlight while they are detached. There are a few limitations for out-of-browser applications. For example, since they are not hosted in the browser, communications with the browser's DOM are not possible like they are with Silverlight applications hosted in the browser.

Figure 2outlines how a Silverlight 3 application can be run in a browser and then detached. Clicking the Detach button runs the event handler shown in Figure 2, which ultimately runs the Application.Current Detach() method. Figure 3shows the architecture. The Application.Current.Detach method will raise an exception if it cannot detach, so some error handling is a good idea.

Figure 2 Detaching from the Browser

private void DetachButton_Click(object sender, RoutedEventArgs e) { try { Application.Current.Detach(); // take the app out of browser } catch (InvalidOperationException opex) { MessageBox.Show("Application is already detached" + " to the desktop."); } catch (Exception ex) { MessageBox.Show("Application could not be detached" + " to the desktop." + Environment.NewLine + ex.Message); } }

fig03.gif

Figure 3 Detaching a Silverlight Application to Run Outside the Browser

The users can then decide if they are sure they want to detach the application from the browser. Silverlight also gives the user the option of adding a shortcut to the desktop and/or to the Start menu for the out-of-browser application. Once the user clicks OK, the application is installed on the desktop and begins launching (hosted by the sllauncher.exe process). At this point, the browser can be closed and the out-of-browser application continues to run on its own.

The application can be removed by right-clicking on the out-of-browser application and choosing Remove Application from the popup menu. This can be done from either the out-of-browser application or from the same version running in the browser. Once removed, the desktop icon and the Start menu item are both removed. It is worth noting that out-of-browser applications will not show up in the Control Panel's add/remove programs list.

Manifest Essentials

Taking an application offline is a simple process for the user and almost as simple from a development standpoint. Silverlight 3 Beta requires a few simple changes to be made to the appmanifest.xml file in the Silverlight project to allow it to be taken out of browser. If these changes are not made, then the Silverlight application cannot be detached and run out of browser. The AppManifest.xml is located in the Properties folder by default and it can be edited manually to include the out-of-browser capabilities.

Figure 4shows the AppManifest.xml file from the sample application with the items of interest in bold in the new Deployment.ApplicationIdentity section. The ShortName is used in the shortcuts for the out-of-browser application (in the Start menu and the desktop shortcut). The Title appears in the title bar of the out-of-browser application. The icons are optional; however, either all of the icons must be included or none are included. This requirement may change in the final release of Silverlight 3, but in the beta, the out-of-browser would not operate properly if some icons are specified and not others. The various icons are used for the Start menu shortcut, the desktop icon shortcut, the icon for the window in the out-of-browser application, and in the dialog that prompts users to decide whether they want to install the application outside the browser.

Figure 4 Setting of the AppManifest.xml

<Deployment xmlns="https://schemas.microsoft.com/client/2007/deployment" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="SilverTwit" EntryPointType="SilverTwit.App"> <Deployment.Parts> </Deployment.Parts> <Deployment.ApplicationIdentity> <ApplicationIdentity ShortName="SilverTwit" Title="SilverTwit - Silverlight Twitter Client"> <ApplicationIdentity.Blurb>Tweet, tweet and retweet</ApplicationIdentity.Blurb> <ApplicationIdentity.Icons> <Icon Size="16x16">images/SilverTwit16.png</Icon> <Icon Size="32x32">images/SilverTwit32.png</Icon> <Icon Size="48x48">images/SilverTwit48.png</Icon> <Icon Size="128x128">images/SilverTwit128.png</Icon> </ApplicationIdentity.Icons> </ApplicationIdentity> </Deployment.ApplicationIdentity> </Deployment>

Running Offline

Another new feature added to Silverlight 3 is the Application.Current.RunningOffline property. This property returns a Boolean value that indicates whether the Silverlight application is running online (in browser) or offline (out of browser). This is useful to know, especially when you might want to run code that communicates with the browser's DOM from Silverlight. If you are running online, the application can communicate with the browser's DOM. However, if you are running offline, the application is hosted in the sllauncher.exe process and does not have a DOM (since it is not a browser). Therefore, before running this code, you could check the RunningOffline property.

When the out-of-browser app first runs, it always opens to a default size. Once open, the window can be resized, maximized, minimized, or closed. The starting size and control of the window itself is not currently a feature in the Silverlight 3 Beta.

The sample application shown in Figure 1is running outside the browser. This is indicated in the lower portion of the window where it says "Running Out of Browser." This check is done using the code shown in Figure 5. If the application were running in the browser, the message would read "Running In Browser" as shown in Figure 6, where the application is running inside the browser.

Figure 5 Online or Offline?

private void SetOfflineStatus() { if (Application.Current.RunningOffline) stats.RunningModeMessage = "Running Out of Browser"; else stats.RunningModeMessage = "Running In Browser"; }

fig04.gif

Figure 6 Running Online

Another new feature of Silverlight 3 is that the application is notified by an event (ExecutionStateChanged) whenever the execution state of the application changes. There are five different states (found in the ExecutionStates enumerator) that can cause this to occur:

  • RunningOnline – The application is now running in the browser.
  • Detaching – The application is detaching from the browser.
  • Detached – The application is now detached from the browser and running outside the browser.
  • DetachedUpdatesAvailable – Same as detached, but it sees that updates are available.
  • DetachedFailed – A detach event failed.

As evidenced in both Figure 1(running offline) and Figure 6(running online), the lower portion of the application shows the current state as Detached since the application has been detached. As the events change, the message in the application automatically updates itself using data binding.

For more information on Data Binding in Silverlight, please refer to my September 2008 Data Points column (" Service-Driven Apps With Silverlight 2 And WCF"). In that column, I discuss data binding and binding modes.

An event handler can be set up to listen for these states by handling the ExecutionStateChanged event, as shown below:

Application.Current.ExecutionStateChanged += new EventHandler(Network_ExecutionStateChanged);

When the ExecutionStateChanged event fires with a state of DetachUpdatesAvailable, the Silverlight 3 out-of-browser application has detected that a newer version of the Silverlight 3 application can be downloaded. The user can then close the out-of-browser application and reopen it to automatically receive the update. Figure 7shows that the message in the out-of-browser application was displayed when the ExecutionStateChanged event fired.

fig05.gif

Figure 7 Updates Are Available

Network Connectivity

Yet another new feature of Silverlight 3 is that it can detect whether a network connection is available, thanks to the NetworkInterface.GetIsNetworkAvailable() method in the System.Net namespace. This check is essential when running an out-of-browser application that must communicate with Web services. If the network connection is down, the application can perform a workaround. Some workaround might include notifying the user of the problem or possibly storing the data locally until a network connection becomes available.

The NetworkChange.NetworkAddressChanged event (also part of the System.Net.NetworkInformation class) executes when it detects a network address change. This event can be handled as shown below:

NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_ NetworkAddressChanged);

The code in Figure 8shows the event handler for the NetworkAddressChange event. The code first sets a Boolean status property of IsNetworkAvailable, which is bound to the Silverlight UI and shows the user the status of the network connectivity. Figure 9shows that the out-of-browser application has detected that the network address has been lost. The bindings updated the message and the status color to red. The simplest way to test this is to open your network connections dialog and disable all network connections. This will cause the NetworkAddressChanged event to fire and the UI to be updated through the data bindings.

Figure 8 Detecting Network Address Changes

private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) { stats.IsNetworkAvailable = NetworkInterface.GetIsNetworkAvailable(); if (NetworkInterface.GetIsNetworkAvailable()) { // get the stored tweet, try to post it if (IsolatedStorageSettings.ApplicationSettings.Contains(TWEET_STORAGE)) { PostTweet(IsolatedStorageSettings.ApplicationSettings[TWEET_STORAGE].ToString()); } } }

fig09.gif

Figure 9 Network Address Unavailable

When the application is running and the network connection is lost, a user might still want to post a message to Twitter. (Keep in mind that even though the network connection may be active, the Twitter service may be down. One way to determine if Twitter is running is to do a ping test against it.) The sample application allows the user to post the message still, but because it cannot be sent to Twitter immediately, the message is stored in Isolated Storage (Silverlight's local persistence store). Figure 8shows that when the network change is detected, if the network just became available and there is a message in Isolated Storage, the message will be posted to Twitter.

For more information on Isolated Storage in Silverlight, please refer to my February 2009 Data Points column " Syndicated Data And Isolated Storage In Silverlight."

Storing Data Offline

If the application cannot detect a network address and a user tries to post a message, the data can be stored in Isolated Storage. The sample application allows only one message to be stored at a time; however, this could be increased by storing each message separately or inside XML. Figure 10shows the code that checks whether the network is available. If it is available, the message is sent on to Twitter. If not, the code checks to see if there is already a message in Isolated Storage. If there is, the user is notified that only one message can be stored at a time.

Figure 10 Sending a Message to Twitter

private void PostTweet() { string tweetText = TweetTextBox.Text; if (!NetworkInterface.GetIsNetworkAvailable()) { if (IsolatedStorageSettings.ApplicationSettings.Contains(TWEET_STORAGE)) { MessageBox.Show("Network connection is not available and only 1 tweet" + " can be stored for delayed posting to Twitter."); } else { IsolatedStorageSettings.ApplicationSettings.Add(TWEET_STORAGE, tweetText); MessageBox.Show("Network connection is not available. The post" + " will be stored until connectivity returns."); } return; } PostTweet(tweetText); }

Out-of-browser applications automatically get 25MB of space available in Isolated Storage. Online browser-hosted Silverlight applications get 1MB of storage. Additional storage can be requested through the IsolatedStorageFile.IncreaseQuoteTo API, which will prompt the user to allow or deny the quota increase.

If there is no message in Isolated Storage, the user's new message is stored and the user is notified that the message will be sent when the network connection is reestablished. When the network address is reestablished, the NetworkAddressChanged event handler will run and will pull the message out of Isolated Storage and submit it (as shown in Figure 8).

As You See, Silverlight 3's out-of-browser solution allows Silverlight applications to run on the desktop without a browser and without a network connection. It has the plumbing to detect network connectivity, to take action when network events occur, and to store data locally if needed. Give it a try. You're sure to come up with some great uses for these new features!

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

John Papa ( johnpapa.net) is a Senior Consultant with ASPSOFT and a baseball fan who spends summer nights rooting for the Yankees with his family. John, a C# MVP, Silverlight Insider, and INETA speaker, has authored several books, including his latest titled Data-Driven Services with Silverlight 2(O'Reilly, 2009). He often speaks at conferences such as Mix, DevConnections, and VSLive.