BackgroundDownloader in MVVM

So I’ve been working on a new view in the Blob Storage Explorer app for Windows 10 today. The transfers view. I have a navigation item for it but right now the screen doesn’t do anything.

The user story for this is:

As a user, I want to be able to see the progress of my downloads so that I know how long before they are done downloading.

There is some trickiness in implementing this.

  1. FileDownloader can be used for ‘in the open’ blobs but a custom background task will be needed for blobs in private containers
  2. File downloading will happen on a different thread than the UI so I need to marshal UI updates across the threading boundary in order to show live download progress within the UI

Below is my current design:

Components of the design include:

  1. Blob List View (and View Model): This is the screen where the user selects the blob they want to download and clicks the download button
  2. Transfer List View (and View Model): This is the screen where I show a history of all file transfers (downloads and uploads…eventually, but just downloads for now)
  3. Transfer Manager: singleton class that manages a list of all active Download Operations (this is a UWP class used by the FileDownloader component). This class maintains the cancellation token, active downloads and delegates to handle all the progress updates / success / failures
  4. Messenger: This is a 3rd party component from MVVM Lite that provides an in-memory pub/sub model that allows me to send messages between components in a decoupled way.
  5. Background Downloader: This is a 1st party component included in the Universal Windows Platform. It will only work for blobs that are accessible through an anonymous internet connection but it seems like the most elegant / consistent way to download blobs. So for starters, I am narrowing scope for Blobs that reside within containers that have either ‘Public Container’ or ‘Public Blob’ Access Levels.

Process Flow (these are the steps I highlighted in blue in the diagram)

  1. User selects the blob they want to download
  2. User clicks download
  3. Blob List View Model ultimately publishes a special message called ‘BlobDownloadRequestedEvent’ that has the source Blob and the target local file to the Messenger.
  4. Transfer Manager (which has been initialized on Application launch) will receive this ‘BlobDownloadRequestedEvent’ and then create a new DownloadOperation using the BackgroundDownloader component. This DownloadOperation is a UWP specific class that has all sorts of hooks into the BackgroundDownloader. It also has a key piece of data that will be used to integrate the UI representation of the download with the I/O representation (the DownloadOperation instance), a unique identifier. This GUID will be used to correlate any models constructed to render progress on the UI and any additional events published to the Messenger.
  5. After the Download Operation is created, hooked up with the Progress Changed delegate we will publish our first ‘BlobDownloadProgressChangedEvent’ which will be received by the TransferListView (if the view has been loaded by the user). It’s important to note that if the user has not navigated to this page yet then the Messenger registration won’t have happened yet and we won’t get any notifications. This is why, when the Transfer List View is navigated to we get the latest state directly from the Transfer Manager and then we start listening for change through the events we receive from the Messenger.

I haven’t tested this implementation yet but I think it will work. I might need some extra plumbing to marshal events across the thread boundaries but I’m pretty sure that’s part of the value that I’m getting just by using the FileDownloader component provided by Microsoft in UWP.

What do you think? Do you like my design? Any suggestions? Tell me what you think in the comments!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s