Using Xamarin.iOS preview of Mobile Services offline

Before we start

The steps below are for the Xamarin plugin for Visual Studio. If you're using Xamarin Studio instead, you should install the nuget addin for Xamarin and most of the instructions should be the same.

Using offline in Xamarin.iOS

  • Create a new Mobile Service or use an existing one and download the Xamarin quickstart for iOS.

  • Open the project and remove the reference to to Azure Mobile Services SDK in Components (we'll be adding a newer on via NuGet)

  • Install the prerelease package of the Mobile Services SQLiteStore using the following command in the Package Manager Console:

    install-package WindowsAzure.MobileServices.SQLiteStore -Pre

  • In the references node, remove the references to System.IO, System.Runtime and System.Threading.Tasks

Edit QSTodoService.cs

  • Add the declarations

     using Microsoft.WindowsAzure.MobileServices; 
    using Microsoft.WindowsAzure.MobileServices.Sync; 
  • Change the type of the member todoTable to

     IMobileServiceSyncTable<ToDoItem> todoTable; 
  • In the constructor for QSTodoService, change the initializer for todoTable:

     todoTable = client.GetSyncTable <ToDoItem> ();
  • In the constructor for QSTodoService, add this as the second line:

  • Add a method InitializeAsync:

     public async Task InitializeStoreAsync()
        string path = "test1.db";
        var store = new MobileServiceSQLiteStore(path);
        await client.SyncContext.InitializeAsync(store);
  • Add a method SyncAsync:

     public async Task SyncAsync()
            await this.client.SyncContext.PushAsync();
            await this.todoTable.PullAsync();
        catch (MobileServiceInvalidOperationException e)
            Console.Error.WriteLine(@"Sync Failed: {0}", e.Message);

Edit QSTodoListViewController.cs

  • Add a call to InitializeStoreAsync in ViewDidLoad(), after the initialization of todoService:

     public override async void ViewDidLoad ()
        base.ViewDidLoad ();
        todoService = QSTodoService.DefaultService;
        await todoService.InitializeStoreAsync();
        ...    // more code
  • Modify the method AddRefreshControl to call SyncAsync before the call to RefreshAsync:

     RefreshControl.ValueChanged += async (sender, e) => {
        await todoService.SyncAsync();
        await RefreshAsync();

Edit ToDoItem.cs

  • Add the using statement:

     using Microsoft.WindowsAzure.MobileServices; 
  • Add the following members to the class ToDoItem:

    public string Version { get; set; }
    public override string ToString()
        return "Text: " + Text + "\nComplete: " + Complete + "\n";

Optional: Add conflict handling

  • In QSTodoService.cs, modify the last line of InitializeAsync to specify a sync handler:

     await client.SyncContext.InitializeAsync(store, new ToDoSyncHandler());  
  • Add a new sync handler:

Running the app

When you launch the app, the list of items will be empty, since it will no longer read items from the mobile service, but rather from the local store. Triggering the refresh operation will result in a call to SyncAsync which will read items from the mobile service into the local SQLite store.

To manually trigger a conflict, you should synchronize changes, then change the item on the server (through either a REST client or SQL Server Management Studio). Then, change the item locally and perform the refresh gesture. If you added the conflict handler, then you will see a dialog that will ask how to resolve the conflict, in favor of the server or client.