People are continually surrounded by devices that are connected to a network. Even the latest refrigerators and washing machines can connect to the internet and home networks. So it’s no surprise that end-users expect their apps to be connected as well. These “connected apps” consume the latest content from the web—social media, digital media, blogs, and other types of content. Developing connected apps has become the norm, but it can still be a challenge to handle common issues like loss of network connectivity, metered network costs, or performance issues. Windows 8 makes it easier than ever before to write a connected app.

In this post, we’ll look at some useful tips to help you provide a fast and fluid, hassle-free, connected experience for users of your Windows Store apps:

  • Pick the right API for your scenarios
  • Choose the right network capabilities
  • Adapt app behavior for metered networks
  • React to network status changes
  • Cache content for fluidity

Let’s dive into the details of each tip.

Pick the right API

If you're going to build a house, you want the right tools. You want a hammer for hammering nails, a saw for cutting boards, and a screwdriver for fastening with screws. In the same way, you’ll want to use the right networking APIs when you develop a connected Windows Store app. Windows 8 provides a variety of networking APIs that your app can use to communicate with other computers and devices over either the Internet or private networks. So your first step is to figure out what networking features your app needs.

The most common networking scenario is to access a web site to retrieve or store information. A simple example would be a game that uses a website to store user information and game scores. A more complex example might be an app that connects to a REST-based web service and uses a library provided by the web service to access or store information. Windows 8 has several APIs that connect with web services and web sites. With these APIs your app can access web services that support REST or send basic HTTP protocol commands (like GET and POST) to a web server. For web access, the API you want depends on the language you use to develop the app:

The following code shows how to perform a basic request and response with a REST-based web service. In this case, the web service could execute an ASP.NET script on the web server.

JavaScript

function makeXHRCall() {
WinJS.xhr({ uri: "http://www.microsoft.com/en-us/default.aspx” }).done(
function onComplete(result) {
print(result.responseText);
},
function onError(err) {
print("
Error: " + err.responseText);
});
}

C#

private async void MakeHttpCall()
{
HttpClient httpClient = new HttpClient();
try {
string response = await httpClient.GetStringAsync("http://www.microsoft.com/en-us/default.aspx");
}
catch (Exception) {
// Handle exception.
}
}

For more info about WinJS.xhr, see Connecting to web services (Windows Store apps using JavaScript and HTML). For more information about HttpClient, see Quickstart: Connecting using HttpClient (Windows Store apps using C#/VB/C++ and XAML) and the HttpClient sample.

Another common networking scenario is downloading or uploading files where the file transfer may take some time. An example would be a camera or photo gallery app that needs to upload or download photos or photo albums from a web service. These transfers can take a lot of time, so it doesn't make sense to have the user wait for the transfer to finish. The Windows.Networking.BackgroundTransfer API provides the ability to download or upload files even when your app is no longer running. The app starts the transfer when it’s running in the foreground and has focus, and Windows 8 then continues the transfer in the background even if the app is no longer running.

Another more specialized scenario is accessing syndicated content. The Windows.Web.Syndication API can retrieve feeds in the RSS or Atom formats. In addition, the Windows.Web.AtomPub API allows an app to publish data in various AtomPub formats.

For scenarios for which a specific, higher-level networking protocol is not available through an API, the Windows Runtime also supports TCP and UDP sockets (along with multicast). The Windows.Networking.Sockets API provides a StreamSocket (TCP) and DatagramSocket (UDP) to let you to implement other, higher-layer protocols.

Note: Windows 8 introduces a new type of socket called a WebSocket. For more information about WebSockets and when to use them, see Connecting with WebSockets.

The following table provides a more complete list of supported networking features, with links to additional information.

 

APIs

Functionality

Examples

Retrieving feeds in the RSS or Atom formats across multiple versions. These APIs make it easy to implement support for newer formats such as OData. The Windows Runtime also supports the Atom Publishing Protocol, enabling the publication of Atom collections.
For more information, see Accessing and managing syndicated content.

Windows.Networking.BackgroundTransfer

Uninterrupted, cost-aware, and resumeable downloading and uploading of content, even when the calling app is not in the foreground. This API supports content transfer using the HTTP, HTTPS, and FTP protocols.
For more information, see Transferring data in the background.

Interacting with REST-based web services and other HTTP-based protocols.
For more information, see Connecting to web services.

Windows.Networking.Proximity

Detecting close proximity between two devices, after which apps can trigger network communication between them using socket APIs.
For more information, see Supporting proximity and tapping.

Windows.Storage.Pickers

Communicating with remote file shares.
For more information, see Accessing data and files.

Windows.Networking.Sockets

Connecting to a service that uses a protocol not supported by APIs already mentioned, like SMTP, MAPI, or telnet, or connecting to another device on the same local network. Also used for apps that require socket-like semantics (asynchronous, bidirectional) to connect through the web (including HTTP proxies) to a new service.
For more information, see Connecting with sockets.

Windows.Storage.ApplicationData

Windows 8 automatically transitions certain application data between user devices. Roaming application data benefits apps where the user utilizes more than one device, such as a PC at work and a tablet at home, and installs the app on multiple devices.
For more information, see Guidelines for roaming application data.

Choose the right network capabilities

Network isolation is part of the app security model used by Windows 8. Windows actively discovers network boundaries and enforces network access restrictions for network isolation. When you deploy them properly, these capabilities help protect your users and apps from malicious attacks.

Apps must declare network isolation capabilities in order to define the scope of network access. Without declaring these capabilities, your app will not have access to network resources. See How to set network capabilities to learn more about how Windows enforces network isolation for apps.

Note that you can’t use networking as an interprocess communication mechanism between a Windows Store app and a desktop app on the same device. So you can’t use IP loopback addresses in a Windows Store app. There are limited exceptions for development purposes that allow use of IP loopback addresses when operating under the Visual Studio debugger. For more information, see How to enable loopback and troubleshoot network isolation.

Network access requests come in two categories:

  1. Outbound, client-initiated requests: Your app acts as the client and initiates network access by sending an initial network request to a remote computer, usually a server. The app sends one or more requests to the server and the server sends back a single response or several responses. For example, all traffic from a web client app to a web server would be in this category.
  2. Inbound, unsolicited requests: Your app acts as a network server and listens for inbound network requests from a remote computer. The remote computer initiates network access by sending an initial request to your app, which acts as a server. The remote computer sends one or more requests to your app, which sends back one or more responses to the remote computer. For example, an app that functions as a media server would be in this category.

Follow the principle of least privilege and add only capabilities your app needs. Your app might need only outbound, client-initiated requests, or it may also need to receive inbound, unsolicited requests. Some apps may also need access to user credentials and certificates when authenticating over a network.

The following table details the network isolation capabilities and other related capabilities often needed for connected apps. The first three are the primary network-isolation capabilities that connected apps use. In fact, your connected app must enable at least one of those first three capabilities. The other entries in the table are additional capabilities often needed by some connected apps.

 

Network capability

Description

Example apps

Internet (Client)

Provides outbound access to the Internet and networks in public places like airports and coffee shops. Most apps that require Internet access should declare this capability.

       

  • RSS readers
  • Social networks
  • Games

Internet (Client & Server)

Provides both inbound and outbound access to the Internet and networks in public places like airports and coffee shops. Inbound access to critical ports are always blocked. This capability is a superset of the Internet (Client) capability; there is no need to declare both.

  • P2P apps
  • Multiplayer games that discover players by using multicast

Private Networks (Client & Server)

Provides inbound and outbound network access at private locations trusted by the user. These are usually home or work networks. Inbound access to critical ports are always blocked.

  • Apps that access network attached storage (NAS) content
  • Line-of-business apps
  • Multiplayer games that discover players by using multicast on a private (home or work) network

Proximity

Required for near-field proximity communication with devices. Allows apps to access the network to connect to a device in close proximity, with user consent to send or accept an invitation.

  • Multiplayer games with people in close proximity

Enterprise Authentication

Provides the capability to connect to enterprise intranet resources that require domain credentials.

  • Line-of-business apps

Shared User Certificates

Provides the capability to access software and hardware certificates, such as smart card certificates, for validating a user's identity. When related APIs are invoked at run time, the user must take action (such as inserting a card or selecting a certificate).

  • Virtual private network apps
  • Line-of-business apps

Use this checklist to make sure network isolation is configured in your app:

  • Determine the direction of network access that your app needs; outbound client-initiated requests, inbound unsolicited requests, or both.
  • Determine the type of network resources that your app will communicate with: trusted resources on a home or work network, resources on the Internet, or both.
  • Configure the minimum required network isolation capabilities in the app manifest. You can do this using the App Manifest Designer in Microsoft Visual Studio 2012, or add them manually.
  • Deploy and run your app to test it using the network isolation tools provided for troubleshooting. For more information, see How to enable loopback and troubleshoot network isolation.

The following screen shot shows how to enable network capabilities using the App Manifest Designer in Microsoft Visual Studio 2012.

Select network capabilities in your app’s package.appxmanifest in Visual Studio 2012

Select network capabilities in your app’s package.appxmanifest in Visual Studio 2012

Adapt app behavior for metered networks

Think about the last time you were approaching your monthly data cap or perhaps travelled abroad. In these situations I typically ended up using my device and apps cautiously to prevent any unnecessary network charges.

Windows 8 addresses this user problem by allowing apps to monitor available network resources and behave accordingly when on metered networks. To promote user confidence in your apps, you can make it able to tell when a connection may incur costs and then adapt its behavior to avoid or reduce charges.

The Windows.Networking.Connectivity API provides info about the type and cost of a network connection. This allows your app to determine when it makes sense to use network resources normally, use them conservatively, or ask the user.

A ConnectionProfile represents a network connection. Your app can use the ConnectionCost of a ConnectionProfile to determine whether to adapt its behavior. The NetworkCostType property indicates the type of a network connection. There are four possible values:

  • Unrestricted—Use of this network connection is unlimited. It has no usage charges or capacity constraints.
  • Fixed—Use of this network connection is unrestricted up to a specific limit.
  • Variable—Use of this network connection is metered on a per-byte basis.
  • Unknown—Cost information is not available for this network connection.

Several other Boolean properties for the ConnectionCost provide still more info.

  • Roaming—The connection is to a network outside of the home provider.
  • ApproachingDataLimit—The connection is approaching the usage allowance specified by the data plan.
  • OverDataLimit—The connection has exceeded the usage allowance specified by the data plan.

Have your app respond to the conditions indicated by these properties. Whenever a connection is Roaming, the data costs associated with network usage could be high. When the NetworkCostType is Variable, the network is a metered network, where the user pays for the amount of data sent or received on the network. When the NetworkCostType is Fixed, there’s cause for concern if the user is already over the data limit or approaching it.

By using this information, an app can follow these guidelines to decide how best to use network resources.

Behavior

Connection cost

App guidelines

Examples

Normal

NetworkCostType is Unrestricted or Unknown and ConnectionCost is not Roaming

App does not implement restrictions. App treats the connection as Unlimited in cost, and unrestricted by usage charges and capacity constraints.

  • Media player app can play an entire HD movie.
  • App can download large file without any restrictions or prompts.

Conservative

NetworkCostType is Fixed or Variable and ConnectionCost is not Roaming or OverDataLimit

App implements restrictions for optimizing network usage to handle operations on metered networks.

  • Media player app can play movies in lower resolutions.
  • App can delay non-critical downloads.

Opt-In

ConnectionCost is Roaming or OverDataLimit

App handles exceptional cases where the network access cost is substantially higher than plan cost.

  • App prompts user to access the network.
  • App suspends all background data network activities.

This code example checks the connection cost and returns suggestions for appropriate app behavior.

JavaScript

var CostGuidance = { Normal: 0, Conservative: 1, OptIn: 2 };
// GetCostGuidance returns an object with a Cost (with value of CostGuidance),
// CostName (a string) and Reason, which says why the cost is what it is.
function GetCostGuidance()
{
var connectionCost = Windows.Networking.Connectivity.NetworkInformation.getInternetConnectionProfile().getConnectionCost();
var networkCostConstants = Windows.Networking.Connectivity.NetworkCostType;
var Retval = new Object();
if (connectionCost.roaming || connectionCost.overDataLimit)
{
Retval.Cost = CostGuidance.OptIn;
Retval.CostName = "OptIn";
Retval.Reason = connectionCost.roaming
? "Connection is roaming; using the connection may result in additional charge."
: "Connection has exceeded the usage cap limit.";
}
else if (connectionCost.networkCostType == networkCostConstants.fixed
|| connectionCost.networkCostType == networkCostConstants.variable)
{
Retval.Cost = CostGuidance.conservative;
Retval.CostName = "Conservative";
Retval.Reason = connectionCost.networkCostType == NetworkCostType.fixed
? "Connection has limited allowed usage."
: "Connection is charged based on usage. ";
}
else
{
Retval.Cost = CostGuidance.Normal;
Retval.CostName = "Normal";
Retval.Reason = connectionCost.networkCostType == networkCostConstants.unknown
? "Connection is unknown."
: "Connection cost is unrestricted.";
}

return Retval;
}

C#

public enum NetworkCost { Normal, Conservative, OptIn };
public class CostGuidance
{
public CostGuidance()
{
var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
Init(connectionCost);
}
public NetworkCost Cost { get; private set; }
public String Reason { get; private set; }


public void Init(ConnectionCost connectionCost)
{
if (connectionCost == null) return;
if (connectionCost.Roaming || connectionCost.OverDataLimit)
{
Cost = NetworkCost.OptIn;
Reason = connectionCost.Roaming
? "Connection is roaming; using the connection may result in additional charge."
: "Connection has exceeded the usage cap limit.";
}
else if (connectionCost.NetworkCostType == NetworkCostType.Fixed
|| connectionCost.NetworkCostType == NetworkCostType.Variable)
{
Cost = NetworkCost.Conservative;
Reason = connectionCost.NetworkCostType == NetworkCostType.Fixed
? "Connection has limited allowed usage."
: "Connection is charged based on usage. ";
}
else
{
Cost = NetworkCost.Normal;
Reason = connectionCost.NetworkCostType == NetworkCostType.Unknown
? "Connection is unknown."
: "Connection cost is unrestricted.";
}
}
}

Use the network information sample to learn more about adapting app behavior for metered networks.

Users can also run Task Manager to see the amount of network data that each app is consuming. This screen shot shows an example.

App History tab in Task Manager allows users to see CPU and network consumption by apps

App History tab in Task Manager allows users to see CPU and network consumption by apps

React to network status changes

In any mobile device scenario, networks can come and go. A mobile 3G or 4G broadband network could go out of range within a user’s home or garage while Wi-Fi is still available. Similarly, Wi-Fi may go out of range when a user leaves home. There may also be times when no network is available. Given the proliferation of Wi-Fi and mobile broadband networks, such network changes occur frequently.

A NetworkStatusChanged event indicates that the available cost or connectivity options may have changed. To react to network status changes and provide a seamless customer experience when a change occurs, have your connected apps follow these scenario guidelines.

Connection loss due to error

In most cases, connections can be reestablished by simply retrying the network operation. If this fails, then wait for a NetworkStatusChanged event. We recommend that apps use an increasing backoff interval between retries, starting with a value of 50 milliseconds and increasing this backoff interval exponentially if connections continue to fail.

Loss of network

Inform the user that the connection has been lost, then register and wait for a NetworkStatusChanged event.

New network availability

There may be cases where the device is connected to multiple networks. For example, a user may be connected to mobile broadband and chatting with friends using the Windows 8 Messaging app before arriving at home and connecting to the unrestricted network there as well. The default policy in Windows 8 is to prefer an unrestricted network over a metered network, and a faster network over a slower network. However, existing connections established by an app do not automatically switch over to a new network. The app must get involved because only the app can make the best decision whether or not to switch to the new network.

For example, if a video stream is close to completion, it may not make sense to switch to the new network. However, if the current network is dropping packets, is too slow, or the stream will take additional time to complete, switching to the new network may be best.

If you determine that switching networks is plausible for your app scenario, follow these guidelines when you detect a new network:

  1. Check the network costs of the existing and new network. If it makes sense to switch to the new network, try making a new network connection and retry the network operation based on the guidelines just mentioned. Windows automatically selects the unrestricted network over the metered network, and the faster network over the slower one if available.
  2. If the new network connection succeeds, use the new network connection in your app and cancel the original network operation on the previous network if the connection already exists.

Change in network cost

A change in network cost can occur when the NetworkCostType is Fixed and usage is approaching the data limit or goes over the data limit. A change in network cost can also result if the NetworkCostType becomes Variable, or if Roaming changes to true. In these cases, adapt app behavior based on the guidelines in the preceding tip.

These code examples use the NetworkStatusChanged event to provide a seamless app experience for various network status changes. Both examples use a global Boolean variable called registeredNetworkStatusNotification, initially set to false.

JavaScript

// Register for NetworkStatusChanged notifications, and display new 
// Internet ConnectionProfile info upon network status change.
function registerForNetworkStatusChange() {
try {

// Register for network status change notifications.
if (!registeredNetworkStatusNotification) {
var networkInfo.addEventListener("networkstatuschanged", onNetworkStatusChange);
registeredNetworkStatusNotification = true;
}
}
catch (e) {
print("An unexpected exception occurred: " + e.name + ": " + e.message);
}
}

// Event handler for NetworkStatusChanged event
function onNetworkStatusChange(sender) {
try {
// Get the ConnectionProfile that is currently used to connect
// to the Internet.
var internetProfile = networkInfo.getInternetConnectionProfile();
if (internetProfile === null) {
print("Not connected to Internet\n\r");
}
else {
internetProfileInfo += getConnectionProfileInfo(internetProfile) + "\n\r";
print(internetProfileInfo);
}
internetProfileInfo = "";
}
catch (e) {
print("An unexpected exception occurred: " + e.name + ": " + e.message);
}
}

C#

// Register for NetworkStatusChanged notifications, and display new 
// Internet ConnectionProfile info upon network status change.
void NetworkStatusChange()
{
// Register for network status change notifications.
try
{
var networkStatusCallback = new NetworkStatusChangedEventHandler(OnNetworkStatusChange);
if (!registeredNetworkStatusNotification)
{
NetworkInformation.NetworkStatusChanged += networkStatusCallback;
registeredNetworkStatusNotification = true;
}
}
catch (Exception ex)
{
rootPage.NotifyUser("Unexpected exception occurred: " + ex.ToString(), NotifyType.ErrorMessage);
}
}

// Event handler for NetworkStatusChanged event
async void OnNetworkStatusChange(object sender)
{
try
{
// Get the ConnectionProfile that is currently used to connect
// to the Internet
ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();

if (InternetConnectionProfile == null)
{
await _cd.RunAsync(CoreDispatcherPriority.Normal, () =>
{
rootPage.NotifyUser("Not connected to Internet\n", NotifyType.StatusMessage);
});
}
else
{
connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);
await _cd.RunAsync(CoreDispatcherPriority.Normal, () =>
{
rootPage.NotifyUser(connectionProfileInfo, NotifyType.StatusMessage);
});
}
internetProfileInfo = "";
}
catch (Exception ex)
{
rootPage.NotifyUser("Unexpected exception occurred: " + ex.ToString(), NotifyType.ErrorMessage);
}
}

To learn more about the NetworkStatusChanged event, see Quickstart: Managing connection events and changes in availability and the Network information sample.

Cache content for fluidity

Caching content to disk lets your app behave fast and fluidly. For example, an RSS feed reader app can immediately display feeds that were cached to disk from a previous session. As soon as the latest feeds are available, the app updates its content. Caching ensures that the user has content to read immediately upon launch while the app gets new content.

Windows 8 provides the ApplicationData class in the Windows.Storage namespace. This class provides access to the app data store. This data store consists of files and settings that are local to the device, roam across multiple devices, or are temporary.

Files are ideal for storing large data sets, databases, or data that is in a common file format. Files can exist in the Roaming, Local, or Temporary folders. Here’s what that means:

  • Roaming files are synchronized across multiple machines and devices where users have signed in with connected accounts. Roaming of files is not instant; the system weighs several factors to determine when to send the data. Keep the use of roaming data below the quota (available via the RoamingStorageQuota property); if the quota is exceeded, roaming of data will be suspended. Files cannot be roamed while an app is writing to them, so be sure to close your app’s file objects when they are no longer needed.
  • Local files are not synchronized across machines. They remain on the machine on which they were originally written.
  • Temporary files are subject to deletion when not in use. The system considers factors such as available disk capacity and the age of a file in determining when or whether to delete a temporary file.

These code examples cache content to disk. Caching the server response allows your app to immediately display content to the user after a termination and relaunch. For brevity, these examples don’t show how to write settings to the app data store or how to respond to roaming events. The Application data sample covers those details.

JavaScript

var roamingFolder = Windows.Storage.ApplicationData.current.roamingFolder;
var filename = "serverResponse.txt";

function cacheResponse(strResponse) {
roamingFolder.createFileAsync(filename, Windows.Storage.CreationCollisionOption.replaceExisting)
.done(function (file) {
return Windows.Storage.FileIO.writeTextAsync(file, strResponse);
});
}

function getCachedResponse() {
roamingFolder.getFileAsync(filename)
.then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file);
}).done(function (response) {
print(response);
}, function () {
// getFileAsync or readTextAsync failed.
// No cached response.
});
}

C#

MainPage rootPage = MainPage.Current;
StorageFolder roamingFolder = null;
const string filename = "serverResponse.txt";

async void cacheResponse(string strResponse)
{
StorageFile file = await roamingFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, strResponse);
}

async void getCachedResponse()
{
try
{
StorageFile file = await roamingFolder.GetFileAsync(filename);
string response = await FileIO.ReadTextAsync(file);
}
catch (Exception)
{
// getFileAsync or readTextAsync failed.
// No cached response.
}
}

For more info about the app data store, see the roaming your app data post and try out the Application data sample.

Wrapping it up

When planning your Windows Store apps, use the guidelines in this post to provide a great, hassle-free, connected experience. These tips can make your development process easier, while maintaining fluidity and boosting user confidence in your apps.

- Suhail Khalid, Program Manager II, Windows

Contributions by: Steven Baker and Peter Smith