Windows 8 and Windows Azure Mobile Services

03 September 2012

Summary:
In this post we look at how to use the newly-launched Windows Azure Mobile Services to provide an easy-to-use cloud storage mechanism for a simple Windows 8 date-tracking application. [Download the Code]

Introduction

On the 28th August 2012, Scott Guthrie announced the launch of Windows Azure Mobile Services. The idea behind this new service is simple: because developers of Windows 8 apps typically may not have the back-end server skills required to create service-based data repositories, Windows Azure Mobile Services provides a simple, REST-based web API for a back-end Azure SQL Database. The developer makes simple HTTP requests to Mobile Services, and receives JSON-based responses. The complexity of the interactions with the Azure SQL Database are completely hidden from the app developer.

An obvious question is, why would they have to use "service-based repositories", why not simply make direct use SQL Server?

The answer is that, by design, Windows 8 store apps can't install or access local databases, (although you can use embedded SQLite), or even use remote database servers. This is all designed to enable Windows 8 store apps to install/uninstall quickly, easily, and without having numerous installation dependencies. That is, these apps have minimal "footprints".

Sign-up for Azure Mobile Services

If you don't already have an account, Microsoft make signing up for Windows Azure extremely easy, straight-forward and worry-free. First, you need to sign up for the 3-month web site trial. Then, select Preview Features, then click the Mobile Services try it now link:

Setup Mobile Services

Once your account has had Mobile Services added as an option, select Mobile Services in the left-column and click on the Create A New App link:

The first thing you need to do is create a URL for your service, and configure the Azure SQL Database you want to use. You can either create one, or use an existing one. I chose to create a new database, because, although I already had one setup, it was located in the North Europe data center. For the duration of the preview, Mobile Services may only be created in the East US region, this means that, although you can setup it this way, having Mobile Services in one region and your database in another would introduce unnecessary latency into the system. So, Microsoft recommends you have both Mobile Services and the back-end database in the same region.


Windows Azure now creates the new Mobile Service, which takes about 10-20 seconds:

If you select the newly created Mobile Service, you should see the following. Click the Data link to create a table to hold your app's data (there's a large + Create link at the bottom of the page):


Table Names

Note that you should name the table with the same name that your app's data model will have (see below). The Azure portal also offers to create an Item table for you. I did use this option myself to try things out quickly. However, the only issue I found with this was that there's no way (from the portal) of deleting a table. You can, of course, connect directly to the Azure SQL database from either Visual Studio's SQL Server Object Explorer, or from SQL Server Management Studio. If you delete tables from a Mobile Service's back-end database in this manner it does not seem, to "register" with the management portal: the table's gone, but the Mobile Service still thinks it's there, and (worse) continually reports errors related to the missing table. So, I had to re-create the deleted tables (from SQL Server Object Explorer) and ended up with several "test" tables that I couldn't remove. It doesn't hurt to leave these unwanted tables lying around, it just bothers my sense of orderliness!

Once you've created the table, return to your service's main page and click the Connect an existing Windows 8 application link. This expands a section of the page as follows:

First, download and install the Mobile Services SDK. When you're done, keep the browser window open, as we'll need to copy the code snippet into our Windows 8 app.

Setup your Windows 8 App

By way of a test, I decided to create (using Visual Studio 2012 RTM) a very simple app based on the Windows store Split App template. The idea behind the app is that it keeps track of "important dates". I called it "Event Tracker". Here I'll concentrate mostly on the mechanics of getting Azure Mobile Services CRUD (Create, Read, Update, Delete) operations working, rather than the coding of specific Windows 8 app features (if you're interested, you can download the all the code from here).

Once the app has been created, add a new class to the DataModel folder. Make sure the class has the same name as the table created earlier on the Azure portal. When you read/write data from/to your Mobile Services table, the public properties of the data model class are mapped to columns in the table. Even better, if you have dynamic schema turned on (which is the default, see the Mobile Services > Configure page on the Azure portal), if you add new properties to the class, Azure will automatically add the required columns to the underlying table. How helpful is that?!

Here's the class I created (EventItem) which will hold a single "event item" (important date). Notice that the class derives from BindableBase, which provides support for auto-firing the PropertyChanged event, when property values in the class are modified. Firing this event is required for correct data binding, which I'll be using to enable the two-way flow of data to/from the data model and the UI:

EventItem

namespace EventTracker.DataModel
{
    public class EventItem : Common.BindableBase
    {
        private static readonly Uri BaseUri = new Uri("ms-appx:///");

        public event EventHandler EventDue;

        private int _id;
        public int Id
        {
            get { return _id; }
            set { this.SetProperty(ref this._id, value); }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { this.SetProperty(ref this._name, value); }
        }

        private string _desc;
        public string Desc
        {
            get { return _desc; }
            set { this.SetProperty(ref this._desc, value); }
        }

        private DateTime? _start;
        public DateTime? Start
        {
            get { return _start; }
            set
            {
                if(this.SetProperty(ref this._start, value))
                    UpdateEventStatus();
            }
        }

        private bool _active;
        public bool Active
        {
            get { return _active; }
            set { this.SetProperty(ref this._active, value); }
        }

        private string _image;
        public string Image
        {
            get { return _image; }
            set { this.SetProperty(ref this._image, value); }
        }

        public void UpdateEventStatus()
        {
            if (Start.GetValueOrDefault().CompareTo(DateTime.Today) <= 0)
            {
                Image = BaseUri + "Assets/Red.png";
                RaiseEventDue();
            }
            else
                Image = BaseUri + "Assets/Green.png";
        }

        protected virtual void RaiseEventDue()
        {
            EventHandler handler = EventDue;

            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    }
}

The EventItem class is very straightforward, and is essentially just a few properties. The Start property is a little different though. When its setter is called, if SetProperty() returns true (meaning that the underlying _start field really did change) then a call is made to UpdateEventStatus(). This checks the date of the event to see if it's either due today, or is in the past. An appropriate image (which will be displayed as the background to a tile in the App's UI) is then attached to the EventItem.Image property.

I also created an EventItemRepository class to hold a collection of EventItems. However, because sometimes I wanted to use test data, and at other times use live Azure Mobile Services data, I abstracted-out the interface for the repository into IEventItemRepository, and then had EventItemRepository and DesignTimeEventItemRepository implement the interface. That way, the App's ItemsPage class would be able to work via the interface, rather than a concrete object. This means that the actual repository to use could be configured via a preferences setting, like so:

private IEventItemRepository _repository;
:
protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    // Create either a design-time or Azure Mobile Services-based repository
    bool useAzureMobileServices = false;  // Off by default
    if (ApplicationData.Current.RoamingSettings.Values.ContainsKey("Repository"))
        useAzureMobileServices = (bool)ApplicationData.Current.RoamingSettings.Values["Repository"];

    if(useAzureMobileServices)
        _repository = new EventItemRepository();
    else
        _repository = new DesignTimeEventItemRepository();
:
:

Here's the definition of IEventItemRepository, EventItemRepository and DesignTimeEventItemRepository. Note that the Azure Mobile Services-related code is highlighted in bold, and that operations like insert, update and delete are a single line of code! Retrieving all the rows in a table is also extremely easy, requiring just a simple LINQ statement:

IEventItemRepository

namespace EventTracker.DataModel
{
    public interface IEventItemRepository
    {
        Task<ObservableCollection<EventItem>> GetAllAsync();
        Task<EventItem> GetAsync(int id);
        Task InsertAsync(EventItem item);
        Task UpdateAsync(EventItem item);
        Task DeleteAsync(EventItem item);
    }
}

EventItemRepository

using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;

namespace EventTracker.DataModel
{
    public class EventItemRepository : IEventItemRepository
    {
        private readonly IMobileServiceTable<EventItem> _mobileServiceTable;
        private ObservableCollection<EventItem> _eventItems;

        public EventItemRepository()
        {
            // Get the Mobile Services table - all CRUD ops will be through the table object
            _mobileServiceTable = App.MobileService.GetTable<EventItem>();
        }

        public static EventItem CreateEmptyEvent()
        {
            var evt = new EventItem
            {
                Active = true,
                Name = "New Event",
                Desc = "Event Description",
                Start = DateTime.Now.AddDays(1)
            };

            return evt;
        }

        public async Task<ObservableCollection<EventItem>> GetAllAsync()
        {
            if (_eventItems != null)
                return _eventItems;

            var query = from eventItem in _mobileServiceTable
                        where eventItem.Active == true
                        select eventItem;

            var results = await query.ToListAsync();
            _eventItems = new ObservableCollection<EventItem>(results);

            return _eventItems;
        }

        public async Task<EventItem> GetAsync(int id)
        {
            if (id < 0)
                throw new ArgumentOutOfRangeException();

            var query = from eventItem in _mobileServiceTable
                        where eventItem.Id == id
                        select eventItem;

            var results = await query.ToListAsync();
            var items = new ObservableCollection<EventItem>(results);

            return items.Count == 0 ? null : _eventItems[0];
        }

        public async Task InsertAsync(EventItem item)
        {
            if(item == null)
                throw new ArgumentNullException();

            _eventItems.Add(item);
            await _mobileServiceTable.InsertAsync(item);
        }

        public async Task UpdateAsync(EventItem item)
        {
            if (item == null)
                throw new ArgumentNullException();

            await _mobileServiceTable.UpdateAsync(item);
        }

        public async Task DeleteAsync(EventItem item)
        {
            if (item == null)
                throw new ArgumentNullException();

            _eventItems.Remove(item);
            await _mobileServiceTable.DeleteAsync(item);
        }
    }
}

DesignTimeEventItemRepository

namespace EventTracker.DataModel
{
    public class DesignTimeEventItemRepository : IEventItemRepository
    {
        private ObservableCollection<EventItem> _eventItems;

        // EventItems property is used by design-time data binding
        public ObservableCollection<EventItem> EventItems
        {
            get
            {
                if (_eventItems != null)
                    return _eventItems;

                _eventItems = new ObservableCollection<EventItem>();

                MockData();
                return _eventItems;
            }
        }

        public async Task<ObservableCollection<EventItem>> GetAllAsync()
        {
            if (_eventItems != null)
                return _eventItems;

            // Simulate network latency
            await Task.Delay(1500);
            await Task.Run(() => MockData());
            return _eventItems;
        }

        private void MockData()
        {
            _eventItems = new ObservableCollection<EventItem>();

            for (var i = 0; i < 5; i++)
            {
                _eventItems.Add(new EventItem
                {
                    Id = i,
                    Active = true,
                    Name = "Name " + i.ToString(),
                    Desc = "This is a description for event item " + i.ToString(),
                    Start = DateTime.Today.AddDays(5*i)
                });
            }            
        }

        public async Task<EventItem> GetAsync(int id)
        {
            :
        }

        public async Task InsertAsync(EventItem item)
        {
            :
        }

        public async Task UpdateAsync(EventItem item)
        {
            :
        }

        public async Task DeleteAsync(EventItem item)
        {
            :
        }
    }
}

Updating App.xaml.cs

Copy & paste the code snippet from the Azure Mobile Services portal and paste it into App.xaml.cs. The application key generated by the portal ties your Windows 8 App to the URL of your Mobiles Services back-end:

sealed partial class App : Application
{
    public static MobileServiceClient MobileService = 
        new MobileServiceClient("https://YOUR_APP_GOES_HERE.azure-mobile.net/", "YOUR_KEY_GOES_HERE");
        :

App Screenshots

Here are a few shots of the completed app:



Conclusion

In this post we looked at how to use the newly-launched Windows Azure Mobile Services to provide an easy-to-use cloud storage mechanism for a simple Windows 8 application. Although it's still in preview, Mobile Services is beautifully quick and easy to setup. I really like the design of the Mobile Services portal, which makes it dead-easy to add Mobile Services to a new, or existing Windows 8 app. The inclusion of cut & pastable code snippets on the portal ensures you're up and running (literally) in minutes. Add the fact that it's a free service during the preview period, Mobile Services is something any Windows 8 developer should try out.


Download the Code

The code for the simple Event Tracker app can be downloaded from here. It was written in XAML/C# using Visual Studio 2012 RTM. To build the app you'll need to download and install the Azure Mobile Services SDK, as well as the Callisto library for Windows 8 XAML-based apps, developed by Tim Heuer (@timheuer).