Building portable C# apps with Mobile Services

I don’t want to be one of those people who’s always going on about their ViewModel, but I was pretty pleased with the way I was able to factor the sample from my Build talk, so I thought I would share. My goal was to structure my Windows Phone 8 code in a way so I could reuse as much of it as possible if I decided to build a Windows Phone 7.5 or Windows Store version of the app.

I mostly followed standard MVVM best practices here, and I assume most of you are familiar with those. I leaned on MvvmLight as my framework of choice. The strategy here was to try to make all ViewModel and Model code easily portable. This was a natural fit with the Portable Class Library (PCL) support introduced in VS 2012. This is the high-level project structure I devised:

image

A lot of the app chrome is deeply platform-specific, so I needed platform-specific projects for those pieces: MyApp.Win8 and MyAppWP8. The key was to separate the ViewModel and Model code, which can be made portable via their own PCL projects: MyApp.ViewModel and MyApp.Model. These projects can be referenced from a variety of C# platforms (.NET, Silverlight, Phone, Windows, even Xbox) without any modification, that’s the beauty of this model.

There is one caveat with a PCL project: the way it works is by exposing a sort of lowest-common-denominator .NET surface area that is guaranteed to work across all the different platforms where that library is supposed to work. Clearly, the further back you go by adding more and more legacy platforms to the supported set, the .NET surface area your project can target shrinks. So you have to make a mindful choice given your business need, luckily VS makes that choice very easy for you. Here is what I picked for my PCL projects:

image

Let’s talk about the two PCL projects in a little bit more detail.

The ViewModel project

This part is not specific to Mobile Services in any way, and has been covered well already by other folks. The key thing to realize is that the ViewModel code needs to depend on the MvvmLight framework. So someone needed to design a subset of MvvmLight that can be referenced from a PCL project. Luckily Laurent has already done the hard work here, so just reference the Portable.MvvmLightLibs project from NuGet, and you’re done.

The Model project

This was the slightly more interesting part, since this is the project that needs to talk to Mobile Services and load/save data for my application. Other than my model classes, which are pretty straightforward, I designed a few service interfaces that my ViewModel code could use to talk to Mobile Services. Here are those interfaces:

public interface IChatService
{
    Task CreateUserAsync(User user);

    Task<ObservableCollection> ReadFriendsAsync(string userId);
    Task<ObservableCollection> CreateFriendsAsync(string userId, string emailAddresses);

    Task<ObservableCollection> ReadPhotoRecordsAsync(string userId);

    Task CreatePhotoRecordAsync(PhotoRecord record);

    Task<ObservableCollection> ReadPhotoContentAsync(string id);
    void DeletePhotoContent(string id);

    Task UploadPhotoAsync(Uri location, string secret, Stream photo);
    Stream ReadPhotoAsStream(Uri location);
    Uri ReadPhotoAsUri(Uri location);

}

public interface IAuthenticationService
{
    Task LoginAsync(string token);
}

My particular scenario revolved around a picture messaging service (ala SnapChat), which hopefully explains the method names; it also supported authentication. 

Once I factored out all the networking via these interfaces, it was super easy to make my app testable. I could write a local mock implementation of the interfaces and my app would work client-side without any networking. I could then write the real implementation and swap these out very easily when I wanted to build the actual working version of the app. The key thing was to use MvvmLight’s support for IoC, so I could easily swap the implementations. The basic principle here is to use a locator every time you need a reference to the implementation of a given service interface. It’s the locator’s responsibility to supply an implementation of the interface. Usually you configure that in one central location, which gives you the ability to switch between implementations with a one-line code change or configuration change. Here’s what the code looks like. In the ViewModel, always reference your services like so: 

IChatService chatService = ServiceLocator.Current.GetInstance<IChatService>();

Then in the ViewModelLocator class, you can switch between implementations:

SimpleIoc.Default.Register<IChatService, ConnectedChatService>();
SimpleIoc.Default.Register<IAuthenticationService, ConnectedAuthService>();

// For testing
// SimpleIoc.Default.Register<IChatService, MockChatService>();
// SimpleIoc.Default.Register<IAuthenticationService, MockAuthService>();

This gives us nice flexibility, but we still haven’t addressed the implementation of ConnectedChatService and ConnectedAuthService: how you actually use Mobile Services from a PCL project.

Implementing ConnectedChatService is very straightforward with the new WindowsAzure.MobileServices SDK on NuGet. One of its least-advertised features is that it fully supports PCL, so you can painlessly reference it from your project and use Mobile Services as you normally would.

Implementing ConnectedAuthService is slightly trickier. The issue here is that MobileServiceClient has two interesting login methods that act slightly differently.

If we are using the Live SDK to log in the user, then you must use the LoginWithMicrosoftAccountAsync method to provide the auth token obtained from Live to Mobile Services. You can use that method from the PCL project so if this is the scenario you’re using, your ConnectedAuthService implementation can live in the PCL project.

If you don’t want to bother with the Live SDK and just want the simplest possible auth experience, you are likely using the LoginAsync method. That method needs platform-specific UI, so it is not available when you use the Mobile Services SDK from the PCL project. But fear not, our project structure allows us to solve this cleanly:

  1. Add a reference to the Mobile Services NuGet package to your platform-specific project (MyApp.Win8 or MyApp.WP8 in the above example). 
  2. Implement ConnectedAuthService in that project
  3. You can now reference LoginAsync.

If you think about it, this actually makes sense. The code for hosting a web view is different on every platform, so the Mobile Services SDK can’t magically make that work in the PCL project. There needs to be some platform-specific code in the SDK that does the right thing per platform, and that’s why the LoginAsync method is only available in the platform-specific project.

Hope this was useful, for more details see the sample code on GitHub.