left-icon

More UWP Succinctly®
by Matteo Pagani

Previous
Chapter

of
A
A
A

CHAPTER 3

Interacting with the network

Interacting with the network


Detecting connectivity

To avoid unexpected errors in your application, it’s always important to check the connectivity before performing any network operation: especially when it comes to mobile scenarios, it can happen that the user finds themselves in an area without network coverage, so we can’t take network connectivity for granted. The following code sample shows how to determine if the Internet connection is available:

protected override void OnNavigatedTo(NavigationEventArgs e)

{

    ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();

    NetworkConnectivityLevel connectivityLevel = profile.GetNetworkConnectivityLevel();

    if (connectivityLevel == NetworkConnectivityLevel.InternetAccess)

    {

        NetworkConnection.Text = "Internet connection available";

    }

    else if (connectivityLevel == NetworkConnectivityLevel.LocalAccess)

    {

        NetworkConnection.Text = "Internet connection not available";

    }

}

The Universal Windows Platform supports multiple connection profiles (identified by the ConnectionProfile class): each of them represents one of the connections that are available in the device. By calling the GetInternetConnectionProfile() method offered by the NetworkInformation class we can get a reference to the connection that provides Internet connectivity.

Then, by calling the GetNetworkConnectityLevel() method on this profile, we can understand if the Internet connection is available or not. This method will return a NetworkConnectivityLevel enumator, which can have multiple values: for our purpose, the two most important ones are InternetAccess (which means that we have connectivity) and LocalAccess (which means, instead, that there’s no Internet connection). In the previous sample, we just display a message to the user, based on the connection status; in a real case scenario, we would always check that the NetworkConnectivityLevel is equal to InternetAccess before performing any network operation.

Another way to properly manage the Internet connection is by using the NetworkStatusChanged event, which is exposed by the NetworkInformation class: this event is triggered every time the status of the connection changes and it’s useful to automatically perform an operation as soon as we have network connectivity. For example, a news reader application could use this event to automatically load the latest news as soon as it detects an Internet connection. The following sample shows how to use this event:

public sealed partial class MainPage : Page

{

    public MainPage()

    {

        this.InitializeComponent();

        NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;

    }

    private void NetworkInformation_NetworkStatusChanged(object sender)

    {

        ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();

        NetworkConnectivityLevel connectivityLevel = profile.GetNetworkConnectivityLevel();

        Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

        {

            if (connectivityLevel == NetworkConnectivityLevel.LocalAccess)

            {

                MessageError.Visibility = Visibility.Visible;

            }

            else if (connectivityLevel == NetworkConnectivityLevel.InternetAccess)

            {

                MessageError.Visibility = Visibility.Collapsed;

                //load the data

            }

        });

    }

}

In the page constructor, we subscribe to the NetworkStatusChanged event: when it’s triggered, we use the same code we’ve previously seen to retrieve the current connection status and to check if we have Internet connectivity. In the sample, we have a TextBlock control in the page with a message that warns the user that the connection is missing: the message is displayed (by setting its Visibility to Visible) when the connection isn’t available; when the connection is back, instead, we hide the message and we load the data from Internet.

Performing network operations: HttpClient

The Universal Windows Platform offers a class called HttpClient that offers many methods to perform the most common network operations, like downloading or uploading a file or interacting with a web service. The HttpClient class leverages a modern approach, which is strictly tied to the HTTP protocol: for every command offered by this protocol (like GET, POST or PUT), you will find a specific method to issue that command.

Note: Please note that the Universal Windows Platform class offers two HttpClient classes: the old one is part of the Microsoft.Net.Http namespace and it’s been added in Windows 8. The new one, instead, is part of the Windows.Web.Http namespace and it’s been introduced in Windows 8.1. In this chapter we’ll focus on the new one.

Download operations

Typically, download operations are performed using a GET command: consequently, you can use the GetAsync() method offered by the HttpClient class. To simplify the developer’s work, the HttpClient class exposes some methods to download the most common data types, like GetStringAsync() (to download text data, like XML or JSON) or GetBufferAsync() (to download binary data, like an image).

Downloading text content is really simple: just pass to the GetStringAsync() method the URL of the text to download.

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    HttpClient client = new HttpClient();

    string result = await client.GetStringAsync(new Uri("https://blogs.windows.com/feed/ ", UriKind.Absolute));

    Result.Text = result;

}

The method simply returns the downloaded string: in the sample, it’s displayed on the page using a TextBlock control.

Otherwise, if you need to download a binary content you can use the GetBufferAsync() method, like in the following sample:

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    HttpClient client = new HttpClient();

    IBuffer buffer = await client.GetBufferAsync(new Uri("http://www.website.com/image.png", UriKind.Absolute));

    StorageFile storageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("picture.png", CreationCollisionOption.ReplaceExisting);

    await FileIO.WriteBufferAsync(storageFile, buffer);

}

By using the WriteBufferAsync() method of the FileIO class we’ve learned to use in the precious chapter, we save an image downloaded from the web to the local storage of the application.

The HttpClient class offers also a way to have more control over the download operation, by using a generic method called GetAsync(): in this case, you won’t get in return directly the resource’s content, but a HttpResponseMessage object, which contains all the properties that defines the HTTP response (like headers, status, etc.). The following code shows the same previous sample (downloading an image and saving it to the store), but performed with the generic method:

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    HttpClient client = new HttpClient();

    HttpResponseMessage response = await client.GetAsync(new Uri("http://www.website.com/image.png", UriKind.Absolute));

    IBuffer buffer = await response.Content.ReadAsBufferAsync();

    StorageFile storageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("picture.png", CreationCollisionOption.ReplaceExisting);

    await FileIO.WriteBufferAsync(storageFile, buffer);

}

The main difference with the previous code is that, since the GetAsync() method is generic, we don’t receive in return directly the content of the requested resource (in this case, the image), but a generic HttpResponseMessage object with the response. To get the real content we need to access to the Content property, which offers some methods to read it based on the type. In this sample, since we’re downloading an image (which is a binary content), we call the ReadAsBufferAsync() method.

Upload operations

Upload operations are usually performed with a POST HTTP command: consequently, we can use the PostAsync() method offered by the HttpClient class. To define the content of the request that we want to send the Universal Windows Platform offers a generic interface called IHttpContent: in the SDK you can find many objects that already implements this class, like HttpStreamContent (to send a binary file), HttpStringContent (to send a text) or HttpMultipartFormDataContent (to send a web form). The following sample shows how to send a file to a web service:

private async void OnUploadFileClicked(object sender, RoutedEventArgs e)

{

    StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync("picture.png");

    IRandomAccessStream accessStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);

    HttpClient client = new HttpClient();

    IHttpContent content = new HttpStreamContent(accessStream.GetInputStreamAt(0));

    await client.PostAsync(new Uri("http://windows.azurewebsites.net/api/values", UriKind.Absolute), content);

}

By using the APIs we’ve learned in the previous chapter, we retrieve the stream with the content of an image stored in the local storage. Then, since we’re dealing with a file (so a binary content) we create a new HttpStreamContent object, passing as parameter the content’s stream. In the end, we simply call the PostAsync() method passing, as parameters, the URL to upload to, a UriKind enumeration value and the content to upload. .

Handling errors

In the beginning of the chapter we’ve learned how to detect if Internet is available before performing a network operation, but most of the times it isn’t enough: the connection, in fact, may drop in the middle of the download or the upload and, in that case, you get an exception that you need to handle, no matter if you’ve previously checked if Internet was available or not.

Let’s see a more detailed sample code:

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    try

    {

        HttpClient client = new HttpClient();

        HttpResponseMessage response = await client.GetAsync(new Uri("http://www.website.com/image.png", UriKind.Absolute));

        if (response.IsSuccessStatusCode)

        {

            IBuffer buffer = await response.Content.ReadAsBufferAsync();

            StorageFile storageFile =

                await

                    ApplicationData.Current.LocalFolder.CreateFileAsync("picture.png",

                        CreationCollisionOption.ReplaceExisting);

            await FileIO.WriteBufferAsync(storageFile, buffer);

        }

        else

        {

            //handle response based on response.StatusCode

        }

    }

    catch (Exception exc)

    {

        //handle other possible exceptions when the connection is lost

    }

}

To handle errors, the generic method is a better choice, because the HttpResponseMessage object we get in return offers a property called IsSuccessStatusCode which returns a bool value that tells us if the operation was completed successfully or not. This way, we make sure that we can properly catch any error before performing any operation with the content.

However, as best practice, it’s still important to embed the usage of the HttpClient class inside a try / catch statement every time we need to perform a network operation, no matter if it’s a download or an upload. The reason is that we may find ourselves in a scenario where we don’t get a response at all (like a time out or a problem in resolving the server’s name): in all these cases, we get an exception, so we need to be ready to handle it properly to prevent crashes. If we want to know more about what happened, we can evaluate the Message property of the exception: typically, it contains a HResult error code, which can be mapped to different issues. Here are some of the most common ones:

  • 0x80072EFD: A connection with the server could not be established
  • 0x80072EE7: The server name or address could not be resolved
  • 0x80072EE2: The operation timed out

Managing the progress

A common requirement when you’re developing an application that can download or upload big files is to track the progress of the operation: this way, the user can have a visual feedback on what’s going on and how much time is left until the operation is completed. To achieve this goal, we can use the generic methods offered by the HttpClient class, which give access to an event called Progress, which is triggered every time a new batch of data has been downloaded or uploaded. Let’s take a look at the following sample:

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    try

    {

        HttpClient client = new HttpClient();

        var operation = client.GetAsync(

        new Uri("http://www.website.com/image.png", UriKind.Absolute));

        operation.Progress = async (result, progress) =>

        {

            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

            {

                if (progress.TotalBytesToReceive.HasValue)

                {

                    double bytesReceived = progress.BytesReceived;

                    double totalBytesToReceive = progress.TotalBytesToReceive.Value;

                    double percentage = (bytesReceived / totalBytesToReceive) * 100;

                    MyProgressBar.Value = percentage;

                }

            });

        };

        HttpResponseMessage response = await operation;

        if (response.IsSuccessStatusCode)

        {

            IBuffer buffer = await response.Content.ReadAsBufferAsync();

            StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("picture.png");

            await FileIO.WriteBufferAsync(file, buffer);

        }

    }

    catch (Exception exc)

    {

        ErrorText.Text = exc.Message;

    }

}

As you can see the biggest difference with the previous code is that we’re invoking the GetAsync() method without using the await prefix: this way, instead of starting immediately the download, we simply get a reference to the Task object. Using this approach, we can subscribe to the Progress event, which provides, in the parameters, some useful properties to understand the status of the operation:

  • If it’s a download operation, we can use the properties called BytesReceived (which contains the number of bytes already downloaded) and TotalBytesToReceive (which contains the size of the file to download in bytes).
  • If it’s an upload operation, we can use the properties called BytesSent (which contains the number of bytes already sent) and TotalBytesToSend (which contains the size of the file to upload in bytes).

In the event handler, thanks to this information, we can calculate the percentage of the operation status and, like in the previous sample, we can assign it to the Value property of a ProgressBar control, to visually display the status to the user. Please note that we’ve used the Dispatcher to perform this operation: the Progress event, in fact, it’s executed on a background thread, while the ProgressBar control is managed by the UI thread. As such, if we would try to update the visual layout of the ProgressBar from a background thread, we would get an exception (we have talked about this potential issue in first chapter of this series of books).

Once we’ve defined the Progress event, we can effectively start the network operation, by simply invoking the operation object with the await prefix. From this point, the code will proceed as usual: when the operation is completed, we get the content of the downloaded file and we store it in the local storage.

Performing download and upload operations in background

All the previous code samples have a limitation, which is related to the application’s lifecycle we’ve learned in the first chapter of this book: when the application is suspended, all the active operations are terminated, including network transfers. If your application uses the network connectivity just to download small files (like a response from a web service in XML or JSON), it’s not a big deal: typically, the user won’t close the application until the data is downloaded, otherwise he won’t be able to properly use the application. However, this consideration doesn’t apply anymore when we’re talking about applications that can download vast amounts of data, like music or videos.

For these scenarios, the Universal Windows Platform has introduced some classes that can keep a download or an upload operation alive even when the app is suspended. Even if these operations are managed directly by the operating system using a separate process, they still belong exclusively to the application: our app will be able just to manage its download and upload operations.

Downloading a file in background

To download a file in background you need to use the BackgroundDownloader class, which creates a download operation starting from a source URL (the file to download) and a destination StorageFile (where to store the file). It’s important to highlight, in fact, that, unlike the HttpClient class, the BackgroundDownloader class can download a file only directly to storage: it can’t keep it in memory, since the download can terminate when the app is not running.

Here is a background download sample:

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    StorageFile file =

    await

    ApplicationData.Current.LocalFolder.CreateFileAsync("demo.zip",

    CreationCollisionOption.ReplaceExisting);

    Uri uri = new Uri("http://www.mywebsite.com/demo.zip", UriKind.Absolute);

    BackgroundDownloader downloader = new BackgroundDownloader();

    DownloadOperation download = downloader.CreateDownload(uri, file);

    await download.StartAsync();

}

After we’ve created a BackgroundDownloader object, we can define the download by calling the CreateDownload() method, which requires as parameters the source URL (the file to download) and a StorageFile object, which represents the file where to write the downloaded content. In the previous sample, we’ve created a file called demo.zip in the local storage where to save our content. The download operation is queued using the StartAsync() method: from now on, the operating system will be in charge of managing it for you.

Since you’re going to use this class especially to download big files, it’s more important than ever to display the status to the user with a progress bar: we can do it using an approach similar to the one we used with the HttpClient class, as you can see in the following sample.

private async void OnStartDownloadClicked(object sender, RoutedEventArgs e)

{

    StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("demo.zip", CreationCollisionOption.ReplaceExisting);

    Uri uri = new Uri("http://www.mywebsite.com/demo.zip", UriKind.Absolute);

    BackgroundDownloader downloader = new BackgroundDownloader();

    DownloadOperation download = downloader.CreateDownload(uri, file);

    Progress<DownloadOperation> progress = new Progress<DownloadOperation>();

    progress.ProgressChanged += progress_ProgressChanged;

    await download.StartAsync().AsTask(progress);

}

void progress_ProgressChanged(object sender, DownloadOperation e)

{

    double bytesReceived = e.Progress.BytesReceived;

    double totalBytes = e.Progress.TotalBytesToReceive;

    double percentage = (bytesReceived / totalBytes) * 100;

    Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

    {

        Progress.Value = percentage;

    });

}

We create a new Progress<DownloadOperation> object that exposes an event called ProgressChanged, which is triggered every time a new batch of data is downloaded. The operation performed in the event handler is the same we’ve seen for the HttpClient class: we simply calculate the progress percentage and we display it using a ProgressBar control. In the end, we call as usual the StartAsync() method to start the operation, but with a difference: we convert it into a Task using the AsTask() method, which accepts as parameter the Progress object we’ve previously created. This way the download will not just start, but it will trigger also the ProgressChanged event every time the progress of the download changes.

Uploading a file in background

The upload operation is very like the download one, as you can see in the following code:

private async void OnStartUploadClicked(object sender, RoutedEventArgs e)

{

    BackgroundUploader uploader = new BackgroundUploader();

    StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("demo.zip");

    Uri destination = new Uri("http://www.qmatteoq.com/upload.aspx", UriKind.Absolute);

    UploadOperation operation = uploader.CreateUpload(destination, file);

    await operation.StartAsync();

}

The only difference is that, in this case, we use the BackgroundUploader class that offers the CreateUpload() method to define the upload operation, which requires the file to destination URL and the file to send (represented, as usual, by a StorageFile object). We have also the chance, however, to send multiple files with one single operation, as you can see in the following sample:

private async void OnStartUploadClicked(object sender, RoutedEventArgs e)

{

    var files = new List<BackgroundTransferContentPart>();

    FileOpenPicker picker = new FileOpenPicker();

    var selectedFiles = await picker.PickMultipleFilesAsync();

    if (selectedFiles != null)

    {

        foreach (StorageFile selectedFile in selectedFiles)

        {

            BackgroundTransferContentPart part = new BackgroundTransferContentPart();

            part.SetFile(selectedFile);

            files.Add(part);

        }

    }

    BackgroundUploader uploader = new BackgroundUploader();

    StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("demo.zip");

    Uri destination = new Uri("http://www.qmatteoq.com/upload.aspx", UriKind.Absolute);

    UploadOperation operation = await uploader.CreateUploadAsync(destination, files);

    await operation.StartAsync();

}

We’re using a FileOpenPicker object, that we’ve learned to manage in the previous chapter: thanks to the PickMultipleFileAsync() method the user is able to select multiple files from his phone, that are returned to the application in a collection. For every file in the collection, we create a new operation part, identified by the BackgroundTransferContentPart class: we add the file simply by calling the SetFile() method and then we add the part to a collection we’ve previously defined.

In the end, we can use an override of the CreateUploadAsync() method of the BackgroundUploader class which accepts, instead of a single file, a collection of BackgroundTransferContentPart object. The work is done: by calling the StartAsync() method we’ll start the upload of all the specified files.

Managing the application’s termination

As you have learned at the beginning of this book, the application can be terminated in case of low resources by the operating system: in this case, since the application is suspended, also the background operations are terminated. Consequently, when the application is reactivated, we’ll need to manually reconnect the background operations to the applications, since they haven’t been kept in memory: for this reason, the BackgroundDownloader and BackgroundUploader classes offers a method that retrieves all the download or upload operations issued by the applications. Let’s see a download sample:

protected override async void OnNavigatedTo(NavigationEventArgs e)

{

    var downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();

    foreach (DownloadOperation download in downloads)

    {

        Progress<DownloadOperation> progress = new Progress<DownloadOperation>();

        progress.ProgressChanged += progress_ProgressChanged;

        await download.AttachAsync().AsTask(progress);

    }

}

private void progress_ProgressChanged(object sender, DownloadOperation e)

{

    double bytesReceived = e.Progress.BytesReceived;

    double totalBytes = e.Progress.TotalBytesToReceive;

    double percentage = (bytesReceived / totalBytes) * 100;

    Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

    {

        Progress.Value = percentage;

    });

}

By using the GetCurrentDownloadsAsync() method we retrieve the list of all the download operations that belong to the application. Then, for each of them, we create a new Progress<DownloadOperation> object, we subscribe to the ProgressChanged event and we call the AttachAsync() method to perform the reconnection. You will notice that the ProgressBar control won’t start from the beginning, but from the last known position before the application was terminated.

Of course, you can use the same approach also for upload operations: in this case, we’ll need to use the GetCurrentUploadsAsync() method of the BackgroundUploader class.

Perform post processing operations

The code we’ve seen so far isn’t something completely new: the same APIs were available, in fact, in Windows and Windows Phone 8.1. However, Windows 10 has added a new important feature: you can now detect when a download operation has completed in background and perform some post processing operations.

This goal can be achieved by leveraging background tasks. We won’t go too much into details now, because another one of the books of this series will contain a chapter completely dedicated to this technology. For the moment, here are just some few basic concepts that you need to know to understand which is their purpose:

  • They are separated projects from the main application, but they belong to the same solution.
  • They are Windows Runtime Components libraries, so they can be used across multiple languages (we’ve talked about them in the first book).
  • They contain some code that can be executed by Windows even when the application is suspended or not running.
  • They are connected to triggers, which are events that cause the execution of the code defined in the background task.

Background tasks are the way how post processing is handled for background transfers: you can create a queue of downloads, start them from the application and, when all of them are finished, a background task can be triggered to perform some additional operations, even if the application isn’t running. For example, you may have a music application that leverages background transfers to allow users to download entire albums in the local storage, so that they can listen to them even without internet connection. Instead of reloading the list of available offline albums when the app is opened again, you can leverage a background task to update the local storage (for example, a database) to store the information that the download has completed successfully and the album is now available for offline listening.

Let’s see first the code we need to handle the post processing. First, we need to add a new Windows Runtime Component to our solution: right click on it, choose Add -> New project and, in the Universal section, choose the Windows Runtime Component (Universal Windows) template. The new project will contain just one class, that you can decide to delete and replace with a new one or just rename it with a more meaningful name. The key to implement a background task is to let this class implement the IBackgroundTask interface: this requirement will force you to define a method called Run(), which is the one that is executed when the background task is launched. In our scenario, this method will be called when the background download operations have completed. Here is how the code of our background task looks like:

namespace Tasks

{

    public sealed class DownloadProcessingTask : IBackgroundTask

    {

        public void Run(IBackgroundTaskInstance taskInstance)

        {

            var details = taskInstance.TriggerDetails as BackgroundTransferCompletionGroupTriggerDetails;

            IReadOnlyList<DownloadOperation> downloads = details.Downloads;

            foreach (DownloadOperation download in downloads)

            {

                //do something with the download

            }

        }

    }

}

The Run() method contains a parameter, with a property called TriggerDetails, which contain all the info about the kind of trigger that activated the task. In the second part of this book we’ll learn that every trigger has a specific type and, typically, this object is important because it contains all the information we need to understand the context. This scenario makes no exception: in case of a background download scenario, the type of this property will be BackgroundTransferCompletionGroupTriggerDetails and it will contain, inside the Downloads collection, the list of all the completed downloads.

Now it’s up to us and to the logic of our application to handle them in the proper way: for example, we can use the DownloadOperation object to retrieve some info about the download (like the name of the file) and store them into a database.

There are two other steps that we need to perform to connect the background task to the main application:

  • Add a reference to the task in the application. Right click on your application’s project in Visual Studio, choose Add reference and, in the Project – Solution section, choose the Windows Runtime Component you’ve just created.
  • You must declare it in the manifest file, in the section called Declarations. You will find a dropdown menu called Available Declarations and one of the items you can add is called Background Tasks. Add it and then configure:
  • In the Properties section, choose Generic as supported task type.
  • In the Entry Point section, specify the full signature of the class that implements the Run() method (in our sample, it’s Tasks.DownloadProcessingTask).

Now that we have our background task up and running, we can move back to the main application and configure the background downloads operations in a way that, when they are completed, they are post processed by it. Here is the code to leverage in the main app:

private async void OnDownloadData(object sender, RoutedEventArgs e)

{

    StorageFile file =

        await

            ApplicationData.Current.LocalFolder.CreateFileAsync("demo.zip",

                CreationCollisionOption.ReplaceExisting);

    Uri uri = new Uri("http://www.mywebsite.com/demo.zip", UriKind.Absolute);

    BackgroundTransferCompletionGroup group = new BackgroundTransferCompletionGroup();

    BackgroundTaskBuilder builder = new BackgroundTaskBuilder();

    builder.Name = "DownloadProcessingTask";

    builder.SetTrigger(group.Trigger);

    builder.TaskEntryPoint = "Tasks.DownloadProcessingTask";

    builder.Register();

    BackgroundDownloader downloader = new BackgroundDownloader(group);

    DownloadOperation firstDownload = downloader.CreateDownload(uri, file);

    Task<DownloadOperation> startTask = firstDownload.StartAsync().AsTask();

    Task task = startTask.ContinueWith(OnDownloadCompleted);

    downloader.CompletionGroup.Enable();

}

private void OnDownloadCompleted(Task<DownloadOperation> obj)

{

    //process the download if it's completed in foreground

}

The first part of the code is nothing different from what we’ve seen before. Since we want to download in background one file, we define the source URL and the destination StorageFile. The difference, compared to the previous code, starts from here. We create a BackgroundTransferCompletionGroup object and we use it for two reasons:

  • First, we need to register the background task in Windows 10, so that the operating system is automatically able to trigger it when the downloads are finished. To do this, we leverage the BackgroundTaskBuilder class and we configure:
  • The Name, which identifies the task univocally in the application.
  • The TaskEntryPoint, which is the full signature of the class defined in the Windows Runtime Component that implements the Run() method. It’s the same value we’ve previously set in the manifest: Tasks.DownloadProcessingTask.
  • The trigger we want to connect to the task, by calling the SetTrigger() method. In this case, the trigger is provided directly by the Trigger property of the BackgroundTransferCompletionGroup we’ve previously created. This trigger will make sure that, when the download operation is completed, the background task will be executed.
  • The last step is to effectively register it, by calling the Register() method of the BackgroundTaskBuilder class.
  • Second, we need to create a BackgroundDownloader object to schedule our download operations. The code is the same we’ve seen in the previous download samples, except that now we are passing, in the constructor of the BackgroundDownloader class, the same BackgroundTransferComplectionGroup object we’ve previously created.

That’s all: now we can create the download in the regular way, like we did before, by calling the CreateDownload() method offered by the BackgroundDownloader class, passing as parameters the source URI and the destination StorageFile. Once we have created it, we can start the operation by calling the StartAsync() method on each of them. The difference compared to the previous approach is that, this time, we don’t start the download immediately (as you can see, we didn’t add the await prefix before): the reason is that, by leveraging the standard async and await approach, we wouldn’t be able to perform the next lines of code until the download is completed. This isn’t the goal we want to achieve: we just need to schedule all the downloads and then, only when they have been completed, we should post process them. The solution is to convert the StartAsync() operation into a Task, by calling the AsTask() method. This will allow us to call on the Task object the ContinueWith() method and specify, as parameter, a method that we want to execute in case the download is completed when the application is still in foreground.

Only at this point, we can start all the downloads operations and enable the background task management, by calling the Enable() method of the CompletionGroup property, exposed by the BackgroundDownloader object. It’s important to do this only when all the background transfers have been created and scheduled.

That’s all: now, when the two downloads will be completed, the background task will be invoked and the Run() method will process the outcome of the operation. However, we need to pay attention that, if the app is running in foreground, both the background task and the foreground handler (the method passed to the ContinueWith() method of the Task) will be invoked: as such, you need to handle this scenario in the proper way, to avoid performing the same operation twice.

Again, in this section we’ve described very quickly how to create and register a background task in a Universal Windows App, so you may have more questions around this topic: don’t worry, another one of the book of this series will contain a chapter that will explain all the details about them.

Interacting with web services

Web services are one of the most widely used approaches when it comes to design a software solution. In the past, typically, applications (websites, desktop apps, etc.) and the backend with the data (like a database) were tightly coupled: the application established a direct connection with the backend and took care of performing the required operations, like retrieving some data or inserting new information. This approach doesn’t fit well the mobile world, since it requires a stable and fast connection between the application and the backend, which can’t be taken for granted on devices like a tablet or a smartphone, that could be connected using a mobile connection.

Services are a way to decouple this tight connection, since they act as an intermediary between the backend and the client: the service will take care of performing the operations on the backend and to prepare the data, so that it can be easily consumed by the mobile application. This approach, among many advantages, is very helpful when our backend needs to expose the data to multiple kind of clients: since service relies on a set of standard technologies (like the HTTP protocol or data formats like XML and JSON), they can be accessed from any application, no matter if it’s a website, a desktop app or a mobile application for Windows, iOS or Android.

REST services

The most common approach to create web services for mobile applications nowadays is by using REST (Representational State Transfer) services. They are very popular for many reasons:

  • They rely on the HTTP protocol, so the operations are defined using the standard commands of the protocol like GET or POST.
  • The endpoints of a REST service are simple URLs. For example, let’s say that you have a service that offers the option to get a list of customers. In this case, it would be enough to perform a GET operation against an URL like http://windows.azurewebsites.net/api/customers
  • They return the data using standard formats like XML or JSON.

Consequently, basically any technology can interact with these kind of services: no matter which platform and language you have chosen to write your application, you’ll always have the chance to perform HTTP requests and to parse XML or JSON data.

When it comes to Universal Windows Platforms apps, the easiest way to interact with REST services is using the HttpClient class we’ve already seen, since it already offers a method for every HTTP command. For example, if your service requires a GET operation to retrieve the results, you can use the GetAsync() method; otherwise, if you need to perform a POST operation to add new data to the backend, you can leverage the PostAsync() method. Since REST services usually return data in XML or JSON format, we can reuse the knowledge we acquired in the previous chapter about serialization. Thanks to the DataContractSerializer and DataContractJsonSerializer classes we can automatically convert the plain data into a collection of objects, which we can manipulate in our Universal Windows Platform apps. Vice versa, when we need to send some data to the service, we need to convert our objects into a XML or JSON structure.

Let’s say, for example, that we need to interact with a REST service which is connected to a database that contains a set of customers. One of the operations offered by the service is to return a list of people, like in the following sample:

[

  {

    "Id":1,

    "Name":"Matteo",

    "Surname":"Pagani"

  },

  {

    "Id":2,

    "Name":"John",

    "Surname":"Doe"

  }

]

The first thing we need, as we did in the previous chapter, is a class that maps this JSON data:

public class Person

{

    public int Id { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }

}

By combining what we’ve learned at the beginning of this chapter about the HttpClient class and the usage of the DataContractJsonSerializer class that we’ve learned in the previous chapter, it should be easy to understand the next code sample:

private async void OnConsumeServiceClicked(object sender, RoutedEventArgs e)

{

    HttpClient client = new HttpClient();

    string result = await client.GetStringAsync(new Uri("http://windows.azurewebsites.net/api/customers", UriKind.Absolute));

    using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(result)))

    {

        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(

        List<Person>));

        List<Person> people = serializer.ReadObject(ms) as List<Person>;

    }

}

By using the GetStringAsync() method of the HttpClient class we retrieve the JSON response from the service. Then, by using the DataContractJsonSerializer class and the ReadObject() method, we deserialize the JSON data into a collection of Person objects. Since the ReadObject() method requires a stream as input and not directly the JSON string, we need first to convert into a MemoryStream object.

Vice versa, here is how we can perform a POST operation to send some data to the service:

private async void OnPostDataClicked(object sender, RoutedEventArgs e)

{

    Person person = new Person

    {

        Name = "Matteo",

        Surname = "Pagani"

    };

    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Person));

    MemoryStream stream = new MemoryStream();

    serializer.WriteObject(stream, person);

    string result = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);

    IHttpContent content = new HttpStringContent(result);

    HttpClient client = new HttpClient();

    await client.PostAsync(new Uri("http://windows.azurewebsites.net/api/customers",UriKind.Absolute), content);

}

In this case we’re performing the opposite operation: we take our objects (in this case, it’s a sample Person object) and we convert it into a JSON structure using the WriteObject() method of the DataContractJsonSerializer class. Again, we need to use a MemoryStream since the method can write the result only to a stream and not directly to a string. In the end, we execute the PostAsync() method of the HttpClient class: since the service accepts the data as a string, we encapsulate the JSON into a HttpStringContent object, that is passed as parameter of the method together with service’s URL.

Tip: When it comes to define the mapping between a class and JSON, it can happen that the operation isn’t so easy to accomplish, especially if the JSON is complex. To make this process easier, Visual Studio offers a feature that is able to this for you: just copy in the clipboard the JSON data returned by your service and choose Edit -> Paste Special -> JSON as class.

Using Json.NET

In the previous chapter, we’ve seen how using the DataContractJsonSerializer class for interacting with JSON data isn’t very straightforward: even though we’re working with strings, we always need to convert them into a Stream object to perform all the required operation.

When it comes to interact with REST services we can simplify our code by introducing Json.NET too.

Let’s see how, thanks to Json.NET, we can simplify the two previous code samples to interact with a REST service. Let’s start with the download sample:

private async void OnConsumeServiceClicked(object sender, RoutedEventArgs e)

{

    HttpClient client = new HttpClient();

    string result = await client.GetStringAsync(new Uri(" http://windows.azurewebsites.net/api/customers ", UriKind.Absolute));

    List<Person> people = JsonConvert.DeserializeObject<List<Person>>(result);

}

The deserialization procedure is performed using the JsonConvert class, which offers a static DeserializeObject<T>() method, where T is the type of data we expect in return: as input, it simply requires the JSON string we’ve just downloaded from the service using the HttpClient class.

Here is, instead, the reverse process to send some data to the service:

private async void OnConsumeServiceClicked(object sender, RoutedEventArgs e)

{

    Person person = new Person

    {

        Name = "Matteo",

        Surname = "Pagani"

    };

    string result = JsonConvert.SerializeObject(person);

    IHttpContent content = new HttpStringContent(result);

    HttpClient client = new HttpClient();

    await client.PostAsync(new Uri("http://windows.azurewebsites.net/api/customers ", UriKind.Absolute), content);

}

Again, the operation is performed using the JsonConvert class: in this case, however, we use the SerializeObject() method, which requires as parameter the object to convert and it simply returns the serialized string. Now we can continue the execution like in the previous sample: we encapsulate the JSON string into a HttpStringContent object and we send it using the PostAsync() method of the HttpClient class.

I won’t describe again the details about how to use Json.NET for more advanced scenarios, like controlling the serialization, dealing with collections or using LINQ to JSON, since they’re the same concepts we’ve already discussed in the previous chapter when we talked about storing JSON data in to the local storage.

Working with RSS feeds

RSS is a widely used standard to aggregate a set of information (like the news published by a website) in a single XML file, that it can be easily processed by a feed reader or by any application that can perform HTTP requests and to parse the XML data. The following sample shows an excerpt from the RSS feed of the Windows blog, which is available at the URL https://blogs.windows.com/feed/

<rss version="2.0"

     xmlns:content="http://purl.org/rss/1.0/modules/content/"

     xmlns:wfw="http://wellformedweb.org/CommentAPI/"

     xmlns:dc="http://purl.org/dc/elements/1.1/"

     xmlns:atom="http://www.w3.org/2005/Atom"

     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"

     xmlns:slash="http://purl.org/rss/1.0/modules/slash/">

  <channel>

    <title>Windows Blog</title>

    <atom:link href="https://blogs.windows.com/feed/" rel="self" type="application/rss+xml" />

    <link>https://blogs.windows.com</link>

    <description></description>

    <lastBuildDate>Fri, 16 Sep 2016 21:00:36 +0000</lastBuildDate>

    <language>en-US</language>

    <sy:updatePeriod>hourly</sy:updatePeriod>

    <sy:updateFrequency>1</sy:updateFrequency>

    <generator>https://wordpress.org/?v=4.5.4</generator>

    <item>

      <title>Animations with the Visual Layer</title>

      <link>https://blogs.windows.com/buildingapps/2016/09/16/animations-with-the-visual-layer/</link>

      <comments>https://blogs.windows.com/buildingapps/2016/09/16/animations-with-the-visual-layer/#respond</comments>

      <pubDate>Fri, 16 Sep 2016 21:00:36 +0000</pubDate>

      <description><![CDATA[When the layout of your Universal Windows Platform (UWP) app changes, there is often a slight pause as your app rearranges content to fit the new window size or orientation. Composition APIs let you create smooth-as-butter animations between these states so your layout changes won’t jar your users. After all, layout changes are a basic [&#8230;]]]></description>

    </item>

  </channel>

</rss>

 

Theoretically, the knowledge acquired in this chapter should be enough to properly manage a RSS feed: since, under the hood, a RSS feed isn’t nothing more than a XML file, we could simply download the RSS content using the HttpClient class and convert it into objects using the DataContractSerializer class or LINQ to XML. However, the Universal Windows Platform includes a set of APIs that can do this operation for us: we’ll just have to provide the URL of the RSS feed to get in return a collection of objects with all the feed items.

The following sample shows how to perform some basic operations:

private async void OnDownloadFeedClicked(object sender, RoutedEventArgs e)

{

    SyndicationClient client = new SyndicationClient();

    SyndicationFeed feed = await client.RetrieveFeedAsync(new Uri("https://blogs.windows.com/feed/ ", UriKind.Absolute));

    Title.Text = feed.Title.Text;

    Description.Text = feed.Subtitle.Text;

    NumberOfItems.Text = feed.Items.Count.ToString();

}

The download operation is performed using the SyndicationClient class, which offers a method called RetrieveFeedAsync(), which simply requires as parameter the RSS feed’s URL. What we get in return is a SyndicationFeed object, which contains a set of properties that are mapped with the data stored in the XML file. In the previous sample, we extract the title, the subtitle and number of items and we display them to the user using a set of TextBlock controls.

All the items that are included in the feed are stored in a collection called Items: each item is represented by the SyndicationItem class, which offers a set of properties that map the XML ones. The following sample shows how to retrieve the first news of the feed (using the FirstOrDefault() LINQ method) and to display to the user its title and summary, stored in the Title and Summary properties.

private async void OnDownloadFeedClicked(object sender, RoutedEventArgs e)

{

    SyndicationClient client = new SyndicationClient();

    SyndicationFeed feed = await client.RetrieveFeedAsync(new Uri("https://blogs.windows.com/feed/ ", UriKind.Absolute));

    if (feed.Items.Count > 0)

    {

        SyndicationItem item = feed.Items.FirstOrDefault();

        FirstNewsTitle.Text = item.Title;

        FirstNewsSummary.Text = item.Summary;

    }

}


Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.