Getting Started with Azure Mobile Services and More

In this post I will describe what I learned in creating my first Windows Store App projects using Azure Mobile Services.

Windows Store app is the current name of the applications designed to run on Windows 8 using WinRT (Windows Run Time).  These types of applications can be download and installed on any machine running Windows 8 operating system using “Store” application.  Did you notice how carefully I jumped around the former name for such applications?

There is an very good walk through for Mobile Service that can be found here https://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started-with-data-dotnet/

Here is my experience.  I create mobile service for my Azure account, calling it MobileContacts. I added just one table called Contact.  Once my SQL Server database was created on Azure, it had one column called “id”.  It is important to notice that the property in your object that you will eventually create has to have the matching name.  If you try, as I did, create property called ContactId, you will get an exception.  Here is my class I am planning to store in that table.

using MobileContacts.Core;


namespace MobileContacts.Data
{
    public class Contact : NotifyPropertyChanged
    {
        private int _id;
        public int id
        {
            get { return _id; }
            set { SetProperty(ref _id, value); }
        }


        private string _firstName;
        public string FirstName
        {
            get { return _firstName; }
            set { SetProperty(ref _firstName, value); }
        }

        private string _lastName;
        public string LastName
        {
            get { return _lastName; }
            set { SetProperty(ref _lastName, value); }
        }


        private string _favoritePicture;
        public string FavoritePicture
        {
            get { return _favoritePicture; }
            set { SetProperty(ref _favoritePicture, value); }
        }

    }
}

 

As you can see, I have other properties as well.  I also have this class implement INotifyPropertyChanged to make sure I can data bind to it properly.  What is cool (or not cool if you are a DBA), the missing columns will be created for me upon my very first insert fired into this table.  Then I followed the link on the portal to install Mobile Services SDK.

image

Now, I am going to create new Store project, using blank app template.

CreateProject

The last step is to add a reference to mobile SDK.

AddReference

Cool.  I am ready to go.  I am going to use MVVM pattern for my C# project, and my first step is to create some base classes.  First one will just implement INotifyPropertyChanged, which is necessary to support data binding.

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace MobileContacts.Core
{
    public abstract class NotifyPropertyChanged : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged
        
        public event PropertyChangedEventHandler PropertyChanged;


        protected void SetProperty<T>(ref T backingField, 
            T newValue, 
            [CallerMemberName] string propertyName = "")
        {
            if(!Equals(backingField, newValue))
            {
                backingField = newValue;
                OnPropertyChanged(propertyName);
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(
                    this, 
                    new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}

I am using cool new CallerMemberName attribute, new to .NET 4.5

Now my base ViewModel.  It will inherit from the NotifyPropertyChanged class above, and will also implement some navigation support.  I am adding support for Go Back button and navigation to another page from the one ViewModel is bound to.  The code is pretty simple, but it comes in quite handy.

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace MobileContacts.Core
{
    public abstract class ViewModel : NotifyPropertyChanged
    {
        protected ViewModel()
        {
            BackButtonCommand = new Command<object>(OnGoBack);
        }

        protected void Navigate<T>(object parameter)
        {
            var rootFrame = Window.Current.Content as Frame;
            if (rootFrame != null)
            {
                rootFrame.Navigate(typeof (T), parameter);
            }
        }

        private Command<object> _backButtonCommand;
        public Command<object> BackButtonCommand
        {
            get { return _backButtonCommand; }
            set {  SetProperty(ref _backButtonCommand, value); }
        }

        protected virtual void OnGoBack(object parameter)
        {
            var rootFrame = Window.Current.Content as Frame;
            if(rootFrame != null)
            {
                rootFrame.GoBack();
            }
        }
        
    }
}

As you can see, I am using commanding based on ICommand interface.  I wrote a very simple implementation of this interface, borrowing concepts from Prism.

using System;
using System.Windows.Input;

namespace MobileContacts.Core
{
    public class Command<T> : ICommand
    {
        private readonly Action<T> _executeMethod;
        private readonly Func<T, bool> _canExecuteMethod;

        public Command(
            Action<T> executemethod, 
            Func<T, bool> canExecuteMethod)
        {
            _executeMethod = executemethod;
            _canExecuteMethod = canExecuteMethod;
        }


        public Command(Action<T> executemethod)
        {
            _executeMethod = executemethod;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecuteMethod == null)
            {
                return true;
            }
            return _canExecuteMethod((T)parameter);
        }

        public event EventHandler CanExecuteChanged;
        protected void OnCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        public void Execute(object parameter)
        {
            _executeMethod((T)parameter);
        }

        public void RaiseCanExecuteChanged()
        {
            OnCanExecuteChanged();
        }

    }
}

Simple, yet effective.  Now let me describe the features I want to implement.

  • Display the list of contacts, showing first name, last name and a favorite image.
  • Ability to view and edit each contact’s details
  • Ability to add a contact
  • Ability to delete a contact.

 

Pretty simple, yet it will allow me to experience Mobile Services.  I am starting with my view model.  Mobile Services SDK contains a few classes, and I am going to use all the basics for now.  First I need to create a client, giving it a URL and an application key.  Both are available on your Azure management portal.  Application key is available via bottom menu bar.

    public class ContactsViewModel : ViewModel
    {
        private const string Url = 
            @"https://yourservice.azure-mobile.net/";
        private const string AppplicationKey = 
            @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

        private readonly MobileServiceClient _client = 
            new MobileServiceClient(Url, AppplicationKey);

Now I am ready to get the data.  I am going to add Init() method to set everything up in my view model

        public void Init()
        {
            _tableOfContacts = _client.GetTable<Contact>();
            Contacts = _tableOfContacts.ToCollectionView();
        }


        private MobileServiceCollectionView<Contact> _contacts;
        public MobileServiceCollectionView<Contact> Contacts
        {
            get { return _contacts; }
            protected set { SetProperty(ref _contacts, value); }
        }

As you can see, I am getting the Contact table, where the class matches the table name.  I am also converting the data to CollectionView, which my GridView control is bound to in XAML.

        <GridView 
            ItemsSource="{Binding Contacts}" 
            ItemTemplate="{StaticResource StandardItemTemplate}"
            SelectedItem="{Binding CurrentContact, Mode=TwoWay}">

        </GridView>

Continuing with my design, I now have to implement my commands.  Command definitions are trivial, but I wanted to talk about the actual command code.

        public void OnAddNew(object parameter)
        {
            CurrentContact = new Contact();
            Navigate<EditContactPage>(this);
        }

        public void OnDelete(Contact contact)
        {
            if (contact != null)
            {
                _tableOfContacts.DeleteAsync(contact);
                OnGoBack(null);
            }
        }

        public void OnSave(Contact contact)
        {
            if (contact != null)
            {
                if (contact.id == 0)
                {
                    if (!Contacts.Contains(contact))
                    {
                        Contacts.Add(contact);
                    }
                    _tableOfContacts.InsertAsync(contact);
                }
                else
                {
                    _tableOfContacts.UpdateAsync(contact);
                }
            }
        }

        public void OnDetails(Contact contact)
        {
            CurrentContact = contact;
            Navigate<EditContactPage>(this);
        }

I have CurrentContact property in my view model, and I am going to bind contact details screen to it.  Thus, in OnAddNew I am creating an instance of the contact, then calling Navigate method you saw earlier.  Since my app is pretty small, I am using the same ViewModel on both list and details pages.  You also see that IMobileServiceTable<Contact> which I keep in _tableOfContacts field can be used to perform CUD operations on contacts.  One line of code everywhere. 

Important Note:

Ideally, I would want to implement some sort of Please Wait overlay in order to let the user know what I am saving the data.  At the same time, I would need to convert my command methods to Async and add IsBusy property to the view model that can be used to be bound to ProgressRign control for example.  This way the user has some visual feedback on his or her actions. 

For this example, I am going to keep it short and simple though. Here is now entire View Model class.

using Microsoft.WindowsAzure.MobileServices;
using MobileContacts.Core;

namespace MobileContacts.Data
{
    public class ContactsViewModel : ViewModel
    {
        private const string Url = 
            @"https://yourservice.azure-mobile.net/";
        private const string AppplicationKey = 
            @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

        private readonly MobileServiceClient _client = 
            new MobileServiceClient(Url, AppplicationKey);

        private IMobileServiceTable<Contact> _tableOfContacts;

        public ContactsViewModel()
        {
            AddNewCommand = new Command<object>(OnAddNew);
            SaveCommand = new Command<Contact>(OnSave);
            DeleteCommand = new Command<Contact>(OnDelete);
            DetailsCommand = new Command<Contact>(OnDetails);
        }


        public void Init()
        {
            _tableOfContacts = _client.GetTable<Contact>();
            Contacts = _tableOfContacts.ToCollectionView();
        }


        private MobileServiceCollectionView<Contact> _contacts;
        public MobileServiceCollectionView<Contact> Contacts
        {
            get { return _contacts; }
            protected set { SetProperty(ref _contacts, value); }
        }


        private Command<Contact> _saveCommand;
        public Command<Contact> SaveCommand
        {
            get { return _saveCommand; }
            set { SetProperty(ref _saveCommand, value); }
        }

        private Command<Contact> _deleteCommand;
        public Command<Contact> DeleteCommand
        {
            get { return _deleteCommand; }
            set { SetProperty(ref _deleteCommand, value); }
        }

        private Command<object> _addNewCommand;
        public Command<object> AddNewCommand
        {
            get { return _addNewCommand; }
            set { SetProperty(ref _addNewCommand, value); }
        }


        private Command<Contact> _detailsCommand;
        public Command<Contact> DetailsCommand
        {
            get { return _detailsCommand; }
            set { SetProperty(ref _detailsCommand, value); }
        }



        public void OnAddNew(object parameter)
        {
            CurrentContact = new Contact();
            Navigate<EditContactPage>(this);
        }

        public void OnDelete(Contact contact)
        {
            if (contact != null)
            {
                _tableOfContacts.DeleteAsync(contact);
                OnGoBack(null);
            }
        }

        public void OnSave(Contact contact)
        {
            if (contact != null)
            {
                if (contact.id == 0)
                {
                    if (!Contacts.Contains(contact))
                    {
                        Contacts.Add(contact);
                    }
                    _tableOfContacts.InsertAsync(contact);
                }
                else
                {
                    _tableOfContacts.UpdateAsync(contact);
                }
            }
        }

        public void OnDetails(Contact contact)
        {
            CurrentContact = contact;
            Navigate<EditContactPage>(this);
        }





        private Contact _currentContact;
        public Contact CurrentContact
        {
            get { return _currentContact; }
            set { SetProperty(ref _currentContact, value); }
        }


    }
}

Could not be much simpler, could it?  Now, let’s take a look at my view model creation.  I am doing it in code behind of the MainPage.  Ideally, I would have some sort of bootstrapper class that I can initialize in App.xamls.cs, but I am taking a few shortcuts in this project.

using MobileContacts.Data;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace MobileContacts
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            var vm = new ContactsViewModel();
            vm.Init();
            DataContext = vm;
        }
    }
}

 

Now, let’s see the XAML code.  I keep it simple, concentrating on tasks at hand.

<Page
    x:Class="MobileContacts.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MobileContacts"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <DataTemplate x:Key="StandardItemTemplate">
            <Button Command="{Binding ElementName=RootGrid, Path=DataContext.DetailsCommand}" CommandParameter="{Binding}">
                <StackPanel Orientation="Vertical" Width="200" Height="250">
                    <TextBlock Text="{Binding LastName}" Style="{StaticResource TitleTextStyle}" HorizontalAlignment="Center" Margin="20,10,20,0"/>
                    <TextBlock Text="{Binding FirstName}" Style="{StaticResource ItemTextStyle}" HorizontalAlignment="Center" Margin="20,10"/>
                    <Image Source="{Binding FavoritePicture}" Stretch="UniformToFill" />
                </StackPanel>
            </Button>
        </DataTemplate>
    </Page.Resources>

    <Grid x:Name="RootGrid" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <GridView 
            ItemsSource="{Binding Contacts}" 
            ItemTemplate="{StaticResource StandardItemTemplate}"
            SelectedItem="{Binding CurrentContact, Mode=TwoWay}">

        </GridView>
        <AppBar VerticalAlignment="Bottom">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal"/>
                <StackPanel Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
                    <Button Command="{Binding AddNewCommand}" Style="{StaticResource AddAppBarButtonStyle}"/>
                </StackPanel>
            </Grid>
        </AppBar>
    </Grid>
</Page>

I have an item template bound to my contact.  I am storing it in Resources on my page.  It is used in the GridView as ItemTemplate. There is something interesting you should notice though. I am using data binding with ElementName to bind my button to a command on view model.  This approach did not work in Silverlight ever, as items in the item control cannot resolve element names outside of the template. Seems like this is fixed in WinRT.  Simplifies my code a bit, which is cool.  App bar just has one button.  All buttons are bound to commands on my view model you saw earlier.  Details page is even simpler.

<Page
    x:Class="MobileContacts.EditContactPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MobileContacts"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.BottomAppBar>
        <AppBar VerticalAlignment="Bottom">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal"/>
                <StackPanel Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
                    <Button Command="{Binding SaveCommand}" CommandParameter="{Binding CurrentContact}" Style="{StaticResource SaveAppBarButtonStyle}"/>
                    <Button Command="{Binding DeleteCommand}" CommandParameter="{Binding CurrentContact}" Style="{StaticResource DeleteAppBarButtonStyle}"/>
                </StackPanel>
            </Grid>
        </AppBar>
    </Page.BottomAppBar>
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Style="{StaticResource BackButtonStyle}" Command="{Binding BackButtonCommand}"></Button>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Text="First Name" HorizontalAlignment="Right" VerticalAlignment="Center" Style="{StaticResource SubheaderTextStyle}"/>
            <TextBlock Text="Last Name" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" Style="{StaticResource SubheaderTextStyle}"/>
            <TextBlock Text="Favorite Picture Url" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Top" Style="{StaticResource SubheaderTextStyle}"/>

            <TextBox Text="{Binding Path=CurrentContact.FirstName, Mode=TwoWay}" FontSize="18" Grid.Column="1"/>
            <TextBox Text="{Binding Path=CurrentContact.LastName, Mode=TwoWay}" FontSize="16" Grid.Column="1" Grid.Row="1"/>
            <TextBox Text="{Binding Path=CurrentContact.FavoritePicture, Mode=TwoWay}" AcceptsReturn="True" IsSpellCheckEnabled="True" TextWrapping="Wrap" FontSize="14" Grid.Column="1" Grid.Row="2"/>
        </Grid>
       
    </Grid>
</Page>

Just a few commands and textboxes.  What is notable though, I do not use code behind anywhere, relying on commands and data binding everywhere.

You can download full project code here.

Please ask any questions you’d like.

Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *