August 2014

Volume 29 Number 8

Windows Store : Integrating OneDrive into Your Windows Store Apps

Tony Champion

You can’t go very far today without running into a conversation about cloud development. Public, private, on- or off-premises, cloud offerings now come in all shapes and sizes. But when talking about consumer-based apps that deal with user files, chances are you’ll focus on offerings like Microsoft OneDrive.

Microsoft OneDrive, recently rebranded, gives consumers a convenient way to store, share and access their personal files from anywhere on any device. OneDrive is now fully integrated into all Microsoft platforms, and it’s compatible with most other platforms currently in use. Documents, photos, videos, and many other types of files can be easily shared, synced or accessed across devices. So, if you’re building an app that involves user files, integrating OneDrive into your app should be an important feature.

If you’re building Windows Store apps, you automatically get a certain level of OneDrive capability for free. In Windows 8.1, you’ll find a Windows Store OneDrive app, as well as desktop integration in the file system that includes an implementation of the File Open Picker and File Save Picker contracts. This means if you use the file open or save pickers in your app, the user will automatically have the ability to open or save documents to his OneDrive account. The same is true for the open and save file dialogs in desktop apps.

However, what happens if you want a little more control over how this interaction works? What if you want to display the user’s data in a different format, or handle the upload or download of multiple files in the background? To address such scenarios, Microsoft provides an API that can be accessed from any platform to allow developers to integrate OneDrive into their solutions. This article explores that API and looks at what’s involved in using this API in your Windows Store apps.

Introducing the Live SDK

Access to the contents of OneDrive is facilitated by the Live SDK. At its core, the Live SDK is a collection of JSON-based REST APIs that can be consumed on any platform. The Live SDK uses single sign-on for Windows Store and Windows Phone Store apps and OAuth 2.0 authentication for other platforms. To help developers create successful applications using OneDrive, Microsoft has also released client-specific SDKs. There are currently SDKs for Microsoft Windows and Windows Phone platforms, as well as SDKs for Android and iOS. Links to all of these SDKs can be found at msdn.microsoft.com/onedrive/dn630256. The Live SDK can also be added via NuGet (nuget.org/packages/LiveSDK).

With regard to OneDrive, the primary role of the Live SDK is to allow programmatic access to the files and folders within a user’s account. Here are the basic services provided by the SDK:

  • Navigate folder hierarchy
  • Create and delete new folders
  • Read and modify folder properties
  • Upload and download files
  • Read and modify file properties
  • Copy and move files and folders
  • Get links to share for files and folders
  • Set permissions on files and folders

I use Visual Studio 2013 Update 2 and the Live SDK version 5.6 to explore how to use the SDK in a Windows 8.1 Store app written in XAML. With the availability of client-specific SDKs for most platforms, the same concepts can easily be migrated to the language and platform of your choice.

Developing Apps with the Live SDK

Before you can start developing apps using the Live SDK, there are a few housekeeping items to address. Because the Live SDK isn’t part of the core Windows SDK, you must download the Live SDK and then add a reference to it from your app. To add the reference, just right-click your solution in Visual Studio 2013 and select Add Reference. The Live SDK can be found in the Windows 8.1 Extensions section of the Reference Manager, as shown in Figure 1.

Adding a Reference to Live SDK
Figure 1 Adding a Reference to Live SDK

By default, a Windows 8.1 Store app has the Internet (Client) capability enabled in its appxmanifest. This is a required capability for using the Live SDK and your project must have it enabled. To verify or enable this capability, open your project’s appxmanifest in the designer and make sure Internet (Client) is checked in the Capabilities tab.

Once the Live SDK has been added to your project, you’ll find the entire SDK in the Microsoft.Live namespace. However, using the SDK at this point will produce a null object reference error. This is because you must register your app with Live services before you can access OneDrive. Depending on the platform on which you’re developing, this can be done in several ways. For a Windows Store app, you simply associate your app with the Windows Store. The most direct way to do this is to use the wizard in Visual Studio.

To launch the wizard, right-click the Store project in the Solutions Explorer and select Store | Associate App with the Store. The wizard will open with a description of what you’ll need in order to continue. Selecting Next prompts you to sign in to a Microsoft account associated with the Windows Store (if you’re not already signed in). You might also have to go through a second verification process, such as receiving an authorization code via a text message to the phone number associated with your account. Once you’ve completed the sign-in process, you’ll see a list of all reserved app names associated with your account, as shown in Figure 2. If this is a new app, you can also reserve a new app name from this screen. Once you have a name to associate your app with, selecting Next will take you to a summary screen and clicking Associate will complete the process.

Associating a Reserved Name with an App
Figure 2 Associating a Reserved Name with an App

Your app is now set up and ready to begin using the Live SDK.

Accessing the User’s Data

The first step to enabling OneDrive integration into your app is gaining the ability to access the user’s information. As previously mentioned, the Live SDK uses 0Auth 2.0 for authorization. However, there are a few additional points to consider aside from simply authenticating your app.

Proper Use of OneDrive If you’re familiar with developing and deploying Windows Store apps, you know there are quite a few guidelines detailing what you can and can’t do within your app. OneDrive adds its own set of guidelines that must also be taken into consideration.

The main reason for the restrictions is to keep you from undermining the user’s trust in OneDrive. When a user has a central source for storing her personal information, she has an inherent trust in that source or she wouldn’t be using it. By accessing OneDrive with your app, the user is extending that trust to your app. So, if your app begins deleting the user’s data without her consent or knowledge, you undermine that trust and affect not only the user’s perception of your app, but also her perception of OneDrive. For that reason, you should take extreme care in how your app interacts with OneDrive, especially when performing functions that update or remove user information. A description of these guidelines can be found at bit.ly/1rQ8iXK.

Using Single Sign-On When using the Live SDK in a Windows Store app, Microsoft suggests you take advantage of its single sign-on (SSO) features. Just as with the Live SDK, adding SSO to your app involves a few additional requirements, like a privacy statement and an account settings panel. Full details on the steps to add the necessary components to your app can be found at bit.ly/TJvTxB.

After your app is prepared for SSO, logging into the user’s account is done using an instance of the LiveAuthClient class. LiveAuthClient has a LoginAsync method that will use the credentials of the Microsoft account that’s currently signed in to the Windows 8.1 device. If sign-in is successful, the returned LiveLoginResult object will contain a LiveConnectSession instance that will be used for all calls to the Live SDK. The following will log the user in and return the Session object:

LiveAuthClient authClient = new LiveAuthClient();
LiveLoginResult authResult = 
  await authClient.LoginAsync(new List<string>() {
  "wl.signin",
  "wl.basic", "wl.skydrive", "wl.skydrive_update" });
if (authResult.Status == LiveConnectSessionStatus.Connected)
{
  // Add code to handle session held in the Session property
}

Scopes You probably noticed the use of scopes like “wl.signin” in the previous code. When your app logs in to a user’s account, it must identify what type of access it needs. If you attempt to use portions of the API you haven’t requested access for, your attempts will fail. For Windows Store apps, this is no different than attempting to use portions of the Windows SDK that you haven’t requested access for in the capabilities section of the package appxmanifest.

The examples in this article will use only the four scopes. The wl.signin scope allows you to take advantage of the SSO behavior you should use in Windows Store apps. The wl.basic scope enables access to some common information about the user.

For OneDrive applications, there are only two additional scopes you need to be concerned with: wl.skydrive and wl.skydrive_update. As the names probably suggest, wl.skydrive is necessary for read and browse access to a user’s OneDrive account. If your app needs the ability to upload files, create or delete folders, or change an object’s properties, you use the wl.skydrive_update scope. This scope also grants you read permission to OneDrive, so you don’t need to include both wl.skydrive and wl.skydrive_update scopes in the access list.

In order to maintain backward compatibility with apps using the previous branding, OneDrive scope names haven’t been changed. However, I wouldn’t be surprised to see a couple of additional scopes using the OneDrive branding appear in future versions of the API.

Because the Live SDK covers a lot more ground than just OneDrive, there many other scopes that I won’t address in this article. You can find a complete descriptive list at msdn.microsoft.com/library/dn631845.

Obtaining User Consent The first time a user runs an app that requests access to his OneDrive account, he will be prompted to grant that app permission to the scopes provided in the login call. Figure 3 shows an example of such a prompt in a Windows Store app. Once the user grants permission, he won’t be prompted again as long as the scope list doesn’t change. If an updated version of the app requests additional features of the API, the user will again be prompted for permission.

Requesting User Consent to Access OneDrive
Figure 3 Requesting User Consent to Access OneDrive

Objects on OneDrive

The OneDrive API considers everything an object. Whether folder, photo, or spreadsheet, everything stored in OneDrive has a set of similar properties and they share API calls. Each object has a collection of properties and may have a collection of child objects. The types of objects I’ll focus on in this article are: Folder, File, Album and Photo. You’ll find a complete list of available objects with their description and use at msdn.microsoft.com/library/dn631843.

Once your app obtains an instance of LiveConnectionSession from the LoginAsync method of LiveAuthClient, that session instance can be used to create an instance of the LiveConnectClient class, which contains all of the API calls you’ll use to interact with OneDrive. The following example shows creating an instance of the LiveConnectClient and querying OneDrive for the user’s root folder object, which can be retrieved using the “me/skydrive” path:

public async Task<object> GetRootFolder()
{
  LiveConnectClient client = new LiveConnectClient(_session);
  LiveOperationResult liveOpResult = 
    await client.GetAsync("me/skydrive");
  dynamic dynResult = liveOpResult.Result;
  return dynResult;
}

This code uses the dynamic keyword to create a class instance of the underlying JSON-formatted string at run time. Though this is quick and easy to use, keep in mind there are some limitations you might run into that would require a more formal class structure.

The results returned from the GetAsync method will contain all of the properties for the requested object. Figure 4 shows an example of the JSON-formattted string returned for a user’s root folder.

Figure 4 JSON Returned from a Folder Object Query

{
  "id": "folder.abced3a35e6d1b",
  "from": {
    "name": null,
    "id": null
  },
  "name": "SkyDrive",
  "description": "",
  "parent_id": null,
  "size": 2957188732,
  "upload_location": 
    "https://apis.live.net/v5.0/folder.abced3a35e6d1b/files/",
  "comments_count": 0,
  "comments_enabled": false,
  "is_embeddable": false,
  "count": 25,
  "link": "https://onedrive.live.com?cid=abced3a35e6d1b",
  "type": "folder",
  "shared_with": {
    "access": "Just me"
  },
  "created_time": null,
  "updated_time": "2014-06-13T18:00:54+0000",
  "client_updated_time": "2012-10-22T19:50:04+0000"
}

When querying within OneDrive, it can be useful to create a more specific query. For instance, the following will return all child objects in the root directory:

LiveOperationResult liveOpResult = await client.GetAsync("me/skydrive/files");

This includes folders and files and could potentially be a lot of data.

What if you want to see only a list of the photos in this directory? This can be accomplished using the filter query parameters. The OneDrive API supports several different types of query parameters in addition to filtering, such as limit, offset and search. The parameters allow you to get just the data you need, and they limit not only the amount of data that must be downloaded, but also the amount of code needed to handle the returned data.

For instance, the following query returns only a list of photos in the root directory, saving you from having to write code to separate out the photos from the folders:

LiveOperationResult liveOpResult =
  await client.GetAsync("me/skydrive/files?filter=photos");

A complete list of query parameters and their use can be found at msdn.microsoft.com/library/dn631842.

Working with Folders

If you’re going to work with a file system of any sort, a logical place to start is with the folder structure. When querying for a folder, you can use two different types of identifiers: a friendly path like me/skydrive or a folder id that looks something like folder.abcde86dfb3a35e6d1b.ABCDED3A35E6D1B!532. If you want to query for a list of a folder’s child objects, you can append “/files” to the path. For instance, the following will return a list of all files, folders, and albums for a given folder id:

LiveOperationResult liveOpResult =
  await client.GetAsync("folder.abcde86dfb3a35e6d1b.ABCDED3A35E6D1B!532/files");

OneDrive contains two types of folder objects: folder and album. An album can be considered a special type of folder found in a user’s root OneDrive directory. Albums can contain photos and videos, as well as a folder structure and additional files.

It’s important to understand the distinction between a folder and an album, because the following query would return only the folders in your root directory and ignore all of the albums. This might cause unexpected results:

LiveOperationResult liveOpResult =
  await client.GetAsync("me/skydrive/files?filter=folders");

To return both folders and albums, use a filter value of “folders,albums.”

The previous query allows you to browse the entire folder structure of a user’s OneDrive account by getting the child folders of each folder. The associated download for this article contains a sample app, MyPhotoAlbum, a XAML Windows Store app containing two pages. The first page, FolderPage, lets you browse your directory structure and shows the results in a GridView. All of the Live SDK calls are wrapped in the OneDriveDataProvider class.

Figure 5 shows the method used to traverse the folder structure by passing in the current folder id and using “folders,albums” as the filter value. If the folder id doesn’t exist, the method defaults to the root directory.

Figure 5 The GetFolderItems Method

public async Task<List<object>> 
  GetFolderItems(string path, string filter)
{
  if (_session == null)
  {
    await InitProvider();
  }
  if (String.IsNullOrEmpty(path))
  {
    path = "me/skydrive";
  }
  if (!String.IsNullOrEmpty(filter))
  {
    filter = "?filter=" + filter;
  }
  LiveConnectClient client = new LiveConnectClient(_session);
  LiveOperationResult liveOpResult =
    await client.GetAsync(path + "/files" + filter);
  dynamic dynResult = liveOpResult.Result;
  return new List<object>(dynResult.data);
}

Figure 6 shows an example of the results returned in the FolderPage. Selecting a child folder will navigate to the same FolderPage, using the child folder as a parameter. This allows the navigation stack to preserve the back functionality to move back up the folder structure.

The FolderPage
Figure 6 The FolderPage

If you’ve requested update access using the wl.skydrive_update scope, you can also create and delete folders using the API. A folder contains only three properties you can create or change: name, description and sort_by. When creating a folder, you must specify a parent directory, either by path or id, and provide a JSON array with, at minimum, a name. Here’s an example of the JSON needed for creating a new folder:

{
 "name": "My Favorite Photos",
 "description": "A folder full of my favorite photos."
}

The SDK handles this through the PostAsync method of the LiveConnectClient. Figure 7 shows the method used to create a new folder.

Figure 7 The CreateFolder Method

public async Task<bool> CreateFolder(string path, string name)
{
  try
  {
    var folderData = new Dictionary<string, object>();
    folderData.Add("name", name);
    LiveConnectClient liveClient = new LiveConnectClient(_session);
    LiveOperationResult operationResult =
      await liveClient.PostAsync(path, folderData);
    dynamic result = operationResult.Result;
    return true;
  }
  catch (LiveConnectException exception)
  {
    return false;
  }
}

Deleting a folder is done using the DeleteAsync method, which can also be used to delete files. It’s important to remember about maintaining OneDrive’s integrity and use any delete function with care:

LiveOperationResult operationResult = await liveClient.DeleteAsync(path);

Working with Files

While the GetAsync method will return a file’s properties, it doesn’t return the file itself. The only way to get a file from OneDrive is by downloading it. The Live SDK for Windows Store apps handles this by creating a download background task, which handles the download asynchronously while not bogging down the device. The following code can be used to download a file from OneDrive:

try
{
  LiveConnectClient liveClient = new LiveConnectClient(_session);
  LiveDownloadOperation op =
    await liveClient.CreateBackgroundDownloadAsync(filePath);
  var result = await op.StartAsync();
  // Handle result
}
catch
{
  // Handle errors
}

Once the background download operation is returned, it must be started by calling the StartAsync method of the LiveDownload­Operation instance.

Similar to downloading a file, the only way to add or update a file in OneDrive is to upload it. In order to upload a file, your app must have requested write access by using the wl.skydrive_update scope. The CreateBackgroundUploadAsync method takes a folder path, a filename, the stream containing the file and an overwrite option. If a file already exists, the overwrite option can either overwrite the original file or it can maintain the original file and rename the new file being uploaded. As with the folder update functions, take care when using this feature not to inadvertently destroy files. The following is an example of how to upload a file:

try
{
  LiveConnectClient liveClient = new LiveConnectClient(_session);
  LiveUploadOperation op = await liveClient.CreateBackgroundUploadAsync(
    path, filename, fileStream, OverwriteOption.Rename);
  var result = await op.StartAsync();
  // Handle result
}
catch
{
  // Handle errors
}

Before uploading a file, it’s important to make sure the user has enough space for the new file. You can verify the amount of available space by using the path “me/skydrive/quota” in the GetObjectAsync method. This will return two properties, quota and available, which let you calculate the number of bytes remaining in the user’s account.

There are two additional features in the API that come in handy when dealing with files. If you want to make a copy of a file, you could download the file and then upload it using a different name. However, that might use a lot of bandwidth for a rather simple operation. Moreover, what if you wanted to copy an entire folder, or move a child folder to a different parent folder? The code and bandwidth to do that using downloads and uploads would make such operations quite cumbersome. To address these functions, the OneDrive API has move and copy commands: MoveAsync and CopyAsync. Both take two parameters: the object—file or folder—to move and the destination path. Figure 8 shows the method used to copy a file.

Figure 8 Copying a File

public async Task<bool> CopyObject(string path, string destination)
{
  if (_session == null)
  {
    await InitProvider();
  }
  try
  {
    LiveConnectClient liveClient = new LiveConnectClient(_session);
    LiveOperationResult operationResult =
      await liveClient.CopyAsync(path, destination);
    return true;
  }
  catch (LiveConnectException exception)
  {
    return false;
  }
}

Wrapping Up

Only so much of an API can be covered in a single article. The Live SDK includes many more features, especially for dealing with photos and videos. If you’re looking at integrating OneDrive into your solution, it would be very beneficial to explore these additional features. Microsoft has created the OneDrive Development Center to give you a single access point for everything related to the OneDrive API at dev.onedrive.com.

Whether you’re building Windows Store apps, Windows Phone Store apps, or an app for any other platform that needs access to a user’s file, adding OneDrive is a great way to integrate your app into a user’s day-to-day life by granting him access to the files that matter most to him. So, as you build your great UX, be sure to include OneDrive.


Tony Champion is president of Champion DS, is a Microsoft MVP, and is active in the community as a speaker, blogger, and author. He maintains a blog at tonychampion.net and can be reached via e-mail at tony@tonychampion.net.

Thanks to the following Microsoft technical expert for reviewing this article: Mimi Sasouvanh
Mimi Sasouvanh is a content developer in the Microsoft Operation Systems Group Content team, writing about OneDrive development and Azure Intelligent Systems Service, among other things. She spends time with family, gardening, and sketching,