February 2016

Volume 31 Number 2

[Windows 10]

Implementing a UWP App with the Official OneDrive SDK

By Laurent Bugnion

In part one of this two-part series (msdn.com/magazine/mt614268), I talked about using the OneDrive APIs over HTTP directly from a Universal Windows Platform (UWP) app, using the HttpClient to place the calls. This gave me the chance to go quite deep into the fundamentals of REST and to see how a .NET application can take advantage of modern programming techniques such as the async/await keywords and the HttpClient library to place calls to modern Web APIs. I also showed how the authentication mechanism works with the OAuth protocol, which lets a user enter his credential in a hosted Web page so that the communication between the user and the credential service is completely transparent to the hosting application. I implemented this using a WebView hosted in a XAML page.

Implementing the authentication and the REST calls isn’t very difficult, but it is work, especially when you want to keep your library up-to-date with all the latest changes and additions. This is why Microsoft has published the OneDrive SDK, which you can add to your application in an easy manner (using the NuGet Package Manager). This is a very useful component, and in the true “new Microsoft” manner, the library is open sourced and published on GitHub at bit.ly/1WX0Y03.

To illustrate this article, a complete sample can be found at galasoft.ch/s/msdnonedrive2.

Authentication with the New SDK

One of the biggest differences between the “low-level” implementation described in the previous article and the official SDK is the authentication mechanism. Previously, I implemented OAuth manually and had to create a number of parts that had to play together:

  • A WebView to present the user with a Web page sent by the Microsoft authentication service, so that the username and password are sent directly to the service, without the application being aware of this.
  • A XAML page hosting the WebView, and waiting to parse the authentication token returned by the service when the process was successful.
  • A client-side authentication service that’s responsible for deciding if the authentication token is available and valid, and for showing the authentication page if that’s not the case.

The new SDK simplifies this greatly, for the developer and for the user.

Authentication for the Developer

For the developer, the authentication process is almost trivial now. The whole workflow is handled by the SDK. Even better, in the background, the SDK uses a feature of Windows Store apps named the OnlineIdAuthenticator. This class handles the authentication mechanism at the OS level and removes the need to parse the authentication token.

In addition to OnlineIdAuthenticator, the OneDrive SDK for Windows 10 also supports the WebAuthenticationBroker class, which provides a more “classic” way of logging in by entering username and password, but also takes care of parsing the authentication token and all dialog with the service. You’ll see examples of these two authentication modes later in this article.

Authentication for the User

For the end user, the main advantage is in OnlineIdAuthenticator taking advantage of the logged-in Windows user’s credentials, which are already available at the OS level. If the Windows user is logging into the OneDrive account associated with his Windows account (which is often the case), he doesn’t even need to re-enter his username and password. The whole authentication mechanism is transparent for him.

Note: In addition to Microsoft Accounts (MSA) for consumers, such as Outlook.com, Live.com or Hotmail.com addresses, the OneDrive SDK also supports Azure Active Directory (Azure AD) for business users. This is great for enterprises whose users are managed this way. MSA is available for the Microsoft .NET Framework 4.5.1 (such as Windows Presentation Foundation applications or Windows Forms), Windows Store and Windows Phone applications. Azure AD is available for Windows Forms, Windows Store 8.1 and UWP apps.

Associating a New UWP App in the Windows Store

For the OnlineIdAuthenticator to work, it’s necessary to register the new application with the Windows Store. Note that you don’t need to actually submit your app to the Windows Store to use the OneDrive SDK. The registration will create some unique IDs for your application, which must be entered into the application manifest (Package.appxmanifest). When users attempt to authenticate themselves to the OneDrive service, these IDs are used to uniquely identify the application. As such, the process of registering your application with the Windows Store replaces the Client ID that you were getting earlier from the OneDrive developer center.

To register your application with the Windows Store, you need to go to the Windows Dev Center at dev.windows.com and log in with your Windows developer account to access the Dashboard. Depending on your status, you might have to register for the account and provide payment information.

Once logged in on the Dashboard, look for the “Submit your app” link. This will take you to an overview page where you can see existing apps and submit the new one, getting it registered with the Windows Store. Creating a new Windows Store app requires a unique app name, which you will enter after clicking the Create a new app button. Then, click on Check availability to make sure the app name you chose is indeed unique. Because the name you chose will be reserved, it’s good practice to use temporary names for test applications that will never be published. This way you avoid blocking another developer’s app name. Also, make sure that you own the rights to the name that you’re reserving to avoid legal actions from a brand owner. Finally, note that if you don’t submit the application within a year, the name reservation will be lost. For the purpose of the sample, I reserved the name TestOneDriveSdk_001, which happened to be available.

Implementing and Testing the Authentication

Now is the time to create the application and to add the OneDrive SDK. First, using Visual Studio, create a new UWP application for Windows 10. The application doesn’t have to have the same name as the one you reserved in the Windows Store, but it is good practice to use the same name.

After the application is created, open the NuGet Package Manager by right-clicking on the project in the Solution Explorer and selecting Manage NuGet Packages from the context menu. Select Browse on top of the Package Manager, search for the Microsoft.OneDriveSDK package and add it to the application.

Now you’ll add authentication to the application with the following steps:

  • Open MainPage.xaml and add a button to the page and name it AuthenticateButton.
  • In MainPage.xaml.cs, implement the Click event handler as shown in Figure 1.

Figure 1 Implementing the Click Event Handler

private IOneDriveClient _client;
public MainPage()
{
  InitializeComponent();
  AuthenticateButton.Click += async (s, e) =>
  {
    var scopes = new[]
    {
      "onedrive.readwrite",
      "onedrive.appfolder",
      "wl.signin"
    };
    _client = OneDriveClientExtensions.GetClientUsingOnlineIdAuthenticator(
      _scopes);
    var session = await client.AuthenticateAsync();
    Debug.WriteLine($"Token: {session.AccessToken}");
  };
}

In the code in Figure 1, you recognize the scopes that you already used in the previous article’s sample. These will provide you with read/write access to the files, as well as the Application folder. As a reminder, this special folder is created in the Apps folder directly under the root and will carry the same name as the application. This is a good place to save roaming settings, online documents and so on.

Before you run the application to test it, you still need to associate it with the Windows Store name that you reserved earlier. To do this, follow these steps:

  • In Solution Explorer, right-click on the project and select Store/Associate App with the Store. This is what you need to do before publishing a UWP app to the Windows Store. In this case, it’s done very early in development because the information generated is needed.
  • In the dialog, Associate Your App with the Windows Store, press the Next button and then sign into the store. Make sure to use the same credentials you used to reserve the name.
  • After signing in, you should see the application name that you reserved. Note that you can also reserve a name directly from this dialog if you don’t want to use the Web-based dashboard.
  • Select the name and click on Next, then on Associate.

Now you’re ready to test the authentication mechanism. Run the application in debug mode and click on the Authenticate button. You should see a dialog on top of your app asking for your consent. Note, however, that you don’t have to enter your Microsoft credentials. Instead, your Windows login credentials are used automatically.

After executing the code in Figure 1, you’ll see the SessionToken (authentication token) in the Output window. You’ll be able to use this token in subsequent API calls just like you did in the first article. If you run the application again later and press Authenticate again, you probably won’t even have to confirm again because your consent is cached until you sign off. This provides a seamless sign-in experience for the user.

Why Can We Not Switch Accounts?

The sample shown in Figure 1 uses the SDK’s GetClientUsing­OnlineIdAuthenticator extension method, which, under the covers, uses the OnlineIdAuthenticator class. As I explained, this object uses the logged-in user’s credentials, which makes the login experience extremely easy for the large majority of users.

The downside of this approach, however, is that there’s no way to select a different account when logging in. As such, this authentication method is great for basic users who have only one OneDrive account associated with their Microsoft accounts. But for power users who have more than one OneDrive account, the OnlineId­Authenticator might be too limited. Thankfully, you can switch to a different method quite easily.

Using a WebAuthenticationBroker

If the user needs to sign in with his credentials explicitly (for example, to let him switch to a different account than the one he logged into Windows with), it’s better to use the WebAuthenticationBroker class. Here, too, the OneDrive SDK is hiding most of the complexity and you can use the following code to create the OneDrive client:

var client = OneDriveClientExtensions.GetClientUsingWebAuthenticationBroker(
  "[CLIENT ID]",
  _scopes);

In the code shown in Figure 1, the [CLIENT ID] string must be replaced with your application’s Client ID. As a reminder, this is a unique ID that you can retrieve in the Windows Dev Center in your application’s details.

If you run the application with this minor change, you’ll now see a different dialog. This dialog lets the user switch to a different account, which is good. However, the user needs to enter his password manually, which is less seamless than the previous workflow. As is usual in engineering, it’s up to you to select the method best suited to the use case you try to solve.

Using the SDK to Access Folders and Files

Once the client is available and authenticated, the OneDrive SDK provides several methods to retrieve information about Drive, Folders and Files. In the previous article, you saw how the file structure is composed of Items, Folders, Files, Audio, Images, Photos and Videos. Until now, you had been getting a JSON response from the service and deserializing it manually into the corresponding C# classes. With the OneDrive SDK, this is no longer necessary because it’ll take care of that step for you. To illustrate this, I’ll rework the same sample application as in the previous article to use the official SDK instead.

Building the Requests

To send requests to the OneDrive REST API, the SDK uses an object hierarchy composed of so-called “request builders.” For example, getting the user’s Drive is done with _client.Drive and getting his Root folder is done with _client.Drive.Root. The most common request builders are listed later in this article.

There are, of course, many possible combinations. Once a request builder has been obtained, the actual request is created by using the Request method, and sent with one of the HTTP methods, for example, GetAsync or PostAsync. For instance, the code in Figure 2will get the metainformation for the file located at the path Public/Test/MyFile.txt and its content as a stream.

Figure 2 Downloading a Text File’s Content

var builder = _client.Drive.Root
  .ItemWithPath("Public/Test/MyFile.txt");
var file = await builder
  .Request()
  .GetAsync();
var contentStream = await builder.Content
  .Request()
  .GetAsync();
Debug.WriteLine($"Content for file {file.Name}:");
using (var reader = new StreamReader(contentStream))
{
  Debug.WriteLine(reader.ReadToEnd());
}

Listing a Few of the Most Common Requests

The most common requests are listed here as request builders:

  • _client.Drive: Builds a request to access the OneDrive itself and get its properties (IDriveRequestBuilder). If you have multiple drives, you can also use _client.Drives, which is an IDrivesCollectionRequestBuilder.
  • _client.Drive.Root: Builds a request to access the OneDrive’s Root folder (IItemRequestBuilder).
  • _client.Drive.Root.Children: Builds a request to get the root folder’s children (IChildrenCollectionRequestBuilder). After the request is executed (with Request().GetAsync()), the result is an IChildrenCollectionPage, which contains a property named NextPageRequest. If the number of children was too large, the NextPageRequest property can be used to access the next page of items.
  • _client.Drive.Root.ItemWithPath("Public/Test"): Builds a request to get the item at the path Public/Test within the root folder (IItemRequestBuilder).
  • _client.Drive.Root.ItemWithPath("Public/Test/MyFile.txt").Content: Build a request to get the content of the file called MyFile.txt (IItemContentRequestBuilder).
  • _client.Drive.Special.AppRoot: Builds a request to access the Application folder (IItemRequestBuilder).
  • _client.Drive.Items[SomeId]: Builds a request to access an item by ID.

Each of these request builders can be seen in action in the sample illustrating this article.

Uploading a File

Uploading a file’s content happens with a PUT request according to the principles of REST APIs. Apart from this difference, the mechanism to build a PUT request is very similar to the GET requests used earlier. In fact, most of the work needed is to actually acquire the Stream. For example, in a UWP app, this can be done with a FileOpenPicker loading the selected file from the Windows file system. The code in Figure 3 shows a simple example (without error handling) uploading the selected file to the Application folder. A more complete example can be found in the code download. In this example, you access the meta information returned by the PutAsync method and save the item’s ID so that you can easily access the saved item later; for instance, to get a link to this item.

Figure 3 Selecting and Uploading a File’s Content

var picker = new FileOpenPicker
{
  SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add("*");
var file = await picker.PickSingleFileAsync();
using (var stream = await file.OpenStreamForReadAsync())
{
  var item = await _client.Drive.Special.AppRoot
    .ItemWithPath(file.Name)
    .Content.Request()
    .PutAsync<Item>(stream);
  // Save for the GetLink demo
  _savedId = item.Id;
}

Once a request for an item has been created, a unique link to this item can be obtained from the OneDrive client with the CreateLink method that returns an IItemCreateLinkRequestBuilder. The following code shows how to do that using the _savedId that you saved earlier when you uploaded a file to OneDrive:

link = await _client.Drive
  .Items[_savedId]
  .CreateLink("view")
  .Request().PostAsync();

Of course, the CreateLink method can be called on any item request (for example, to get a link to a folder and so on). Note that the request created by the CreateLink method needs to be POSTed to the service. The CreateLink method requires one parameter that can be “view” or “edit.” Depending on the value of this parameter, a read-only link or a read-write link will be created.

Updating an Item

Updating an item’s metainformation happens with a request builder and the UpdateAsync method. For example, after you upload a file as shown earlier in this article, you can use its ID (which you saved in the _savedId attribute) to modify its name with the code shown here:

var updateItem = new Item
{
  Name = "[NewNameHere]"
};
var itemWithUpdates = await _client
  .Drive
  .Items[_savedId]
  .Request()
  .UpdateAsync(updateItem);

Moving an Item

Moving an item to a new location is a special case of updating its properties. In this case, you’ll update its ParentReference property, which contains information about the item’s location in OneDrive. If you modify this property with a new location and update the OneDrive item accordingly, the item will be moved.

In the following sample, you take the file that you uploaded earlier (having saved its ID in the _savedId attribute) and move it from its original location into the Root folder (of course in a real life application, some error handling needs to be added to this code):

var newLocation = await _client.Drive.Root.Request().GetAsync();
var updateItem = new Item
{
  ParentReference = new ItemReference
  {
    Id = newLocation.Id
  }
};
var itemWithUpdates = await _client
  .Drive
  .Items[_savedId]
  .Request()
  .UpdateAsync(updateItem);

Copying an Item

Copying an item is a little different than moving it. Interestingly, when you move or rename an item, the result of the asynchronous operation comes immediately, and is the Item instance with the new metainformation (such as the new location or the new name). When you copy an item, however, this can take a while and instead of waiting until the operation is completed, the SDK returns an instance of IItemCopyAsyncMonitor as soon as the copy operation begins.

This instance has one method called CompleteOperationAsync, which polls the result of the copy operation on OneDrive, updates an optional progress provider and returns the Item instance only when the copy operation is completed. This provides a very nice UX because it’s possible to do another operation at the same time and notify the user when the copy operation is finished. Of course, just as with every long-lasting operation, it’s possible to cancel the polling (however, this will not cancel the copy operation itself!). The code in Figure 4 shows how the item that was uploaded to the Application folder can be copied to the Root folder. First, you retrieve the Root folder itself. Then, you get the file in order to construct a new unique name (to avoid collisions). Finally, the Copy request is created and executed by a POST to the server. Note how you then use the CompleteOperationAsync method to wait and notify the user when the copy operation is done.

Figure 4 Copying the Newly Uploaded Item to the Root

var newLocation = await _client.Drive.Root.Request().GetAsync();
// Get the file to access its meta info
var file = await _client.Drive.Items[_savedId].Request().GetAsync();
var newName = Path.GetFileNameWithoutExtension(file.Name)
  + "-"
  + DateTime.Now.Ticks
  + Path.GetExtension(file.Name);
var itemStatus = await _client
  .Drive
  .Items[_savedId]
  .Copy(
    newName,
    new ItemReference
    {
      Id = newLocation.Id
    })
  .Request()
  .PostAsync();
var newItem = await itemStatus.CompleteOperationAsync(
  null,
  CancellationToken.None);
var successDialog = new MessageDialog(
  $"The item has been copied with ID {newItem.Id}",
  "Done!");
await successDialog.ShowAsync();

Creating a New Folder

There are more operations possible in the SDK, but before I move on, I want to mention another interesting feature: creating a new folder. This is interesting because it acts on a collection (the parent folder’s Children) by adding an item and then sending the request to OneDrive as shown in Figure 5. Note that in this case the method used (AddAsync) doesn’t directly correspond to an HTTP method (GET, POST, PUT and so on). Once the folder is created, the newFolderCreated variable contains the necessary information, especially the folder’s ID:

Figure 5 Creating a New Folder

var newFolder = new Item
{
  Name = NewFolderNameText.Text,
  Folder = new Folder()
};
var newFolderCreated = _client.Drive
  .Special.AppRoot
  .Children
  .Request()
  .AddAsync(newFolder);
var successDialog = new MessageDialog(
  $"The folder has been created with ID {newFolderCreated.Id}",
  "Done!");
await successDialog.ShowAsync();

Signing Off and More

Finally, once the work with the client is finished, the user can choose to sign off. This is easy to do by using the OneDrive client’s SignOutAsync method.

In addition to the methods and properties described in this article, there are a few more functionalities in the SDK. To make sure to get the latest and greatest documentation, you can check two different documentation sources:

  • The OneDrive C# SDK on GitHub has quite a lot of documentation available. You can find it at bit.ly/1k0V2AL.
  • The OneDrive API itself is documented at bit.ly/1QniW84.

Error Handling

If anything wrong happens with the service call, a OneDrive­Exception will be thrown. However, the exception message doesn’t contain information about the actual error. Instead, the error detail is contained in the OneDriveException’s Error property (of type Microsoft.OneDrive.Sdk.Error). This is where you’ll find the error message, as well as additional data to help you solve the issue.

Because errors can be nested, you can easily use the IsMatch method to look for a specific error code anywhere in the error hierarchy, for example with:

theException.IsMatch(OneDriveErrorCode.InvalidRequest.ToString());

Getting and Building the SDK Source

While the SDK can be added using the NuGet Package Manager, it can be useful to get the source code; for example, to make changes or add features to the code. This can be done easily, either by downloading the source code, or (even better) by forking the source code from GitHub and modifying your branch.

The OneDrive SDK source code is available at bit.ly/1WX0Y03. In order to get the code and create a fork, you can use your favorite GitHub client, such as GitHub Desktop (desktop.github.com). Once you get the code on your local machine, you can build it in Visual Studio and add it to your application as a project reference, for example. From this point forward, you’re at the same point as after adding the SDK through NuGet.

Wrapping Up

In the first article of this series, you saw how you can build a powerful library calling into a REST API by using the HttpClient, the async/await keywords and a JSON serializer. However, while these days this is much easier than it used to be, it’s still a lot of work, especially when you want to keep your library up-to-date with new features.

In this article, I took the other approach, which is to use the OneDrive SDK built by Microsoft. You saw how the library can be added to a UWP application, how the authentication works (either by using the logged-in user’s credentials transparently or by using the WebAuthenticationBroker and offering to the user the possibility to select a different account and so on). I also demonstrated the most useful item operations such as getting an item information by its path or ID, getting a folder’s children, downloading, renaming, moving or copying a file, getting a unique share link to an item, and more.

With the OneDrive SDK available on GitHub in open source and Microsoft actively developing new features and fixing issues, it’s easier than ever to access OneDrive from your UWP apps. This opens the door to a range of features such as roaming settings, sharing documents between devices and more.


Laurent Bugnion is senior director for IdentityMine, one of the leading companies (and a gold partner) for Microsoft technologies. He is based in Zurich, Switzerland. His 2010 book, “Silverlight 4 Unleashed,” published by Sams, is an advanced sequel to “Silverlight 2 Unleashed” (2008). He writes for several publications, is in his ninth year as a Microsoft MVP and is in his second year as a Microsoft Regional Director. He’s the author of the well-known open source framework MVVM Light for Windows, WPF, Xamarin and of the popular Pluralsight reference course about MVVM Light. Reach him on his blog at galasoft.ch.

Thanks to the following Microsoft technical expert for reviewing this article: Gina Chernoby