June 2017

Volume 32 Number 6

[Xamarin]

Authentication and Data Access with Visual Studio Mobile Center

By Alessandro Del

At Connect(); 2016, Microsoft unveiled a preview of Visual Studio Mobile Center (mobile.azure.com), a new portal that offers—in one place—everything developers need to build mobile apps in a DevOps approach, from back-end services and continuous integration, to analytics and test automation. Visual Studio Mobile Center puts together the tools and services Microsoft has been offering through Microsoft Azure Mobile Apps, Visual Studio Team Services, Xamarin Test Cloud and HockeyApp. I recommend you read the article, “Mobile DevOps Exploring Visual Studio Mobile Center,” by Thomas Dohmke (bit.ly/2f7a8Wk) for a general overview of what’s available in Visual Studio Mobile Center.

In this article, I’ll focus on authentication and tables with a practical approach, describing how to consume these services from a cross-platform app that runs on Android and iOS, built with Xamarin.Forms. The sample app will show and store a list of books a user purchased and is based on the Model-View-ViewModel (MVVM) pattern for better code reuse. Some of the features described here require an Azure subscription. If you don’t have one, you can request a free trial at azure.microsoft.com. You need Visual Studio 2017 or 2015 with the latest Xamarin extensions installed to build the sample application. You can download the free Community edition from visualstudio.com.

Adding an App to the Visual Studio Mobile Center

In order to leverage any service from Visual Studio Mobile Center, the first thing you need to do is associate a new app to the portal. To accomplish this, you need to enter the portal (mobile.azure.com) and sign in with either a Microsoft or GitHub account. The welcome page of the Mobile Center shows a button called Add new app. As shown in Figure 1, when you click this button, you need to specify the app name, an optional description, the target OS and the development platform.

Adding an App to Visual Studio Mobile Center
Figure 1 Adding an App to Visual Studio Mobile Center

At the time of this writing, Mobile Center only supports iOS and Android applications (support for Windows is planned), and the list of available development platforms varies depending on the OS of your choice. Enter the information as shown in Figure 1, making sure you select Xamarin, and click Add new app. Feel free to select iOS instead of Android if you have a Mac computer that you can use to build Xamarin projects, as the sample code will run on both. Also, you can associate an app twice in order to enable the support for analytics and crash reports on both OSes.

After this, the Visual Studio Mobile Center shows how to include analytics and crash reports in a Xamarin app (including Xamarin.Forms) using the Mobile Center SDK NuGet packages. This will be done later in the sample code, so let’s move forward.

Creating Tables

You’ll now set up a new table to store a list of books, so click Tables in the toolbar. Because Mobile Center relies on the Azure platform for identity and tables, you’ll be asked to connect your Azure subscription with the Connect Subscription button. Once the subscription has been connected, you’ll be able to click Create Table to get started. At this point, Visual Studio Mobile Center creates a new mobile app back end and an app endpoint in the Azure Mobile Apps service. See the endpoint form at https://mobile-{your-app-id}.azurewebsites.net/. In the popup that appears, enter Book as the new table name. Then, select Authenticated, Soft delete and Per-user data checkboxes and unselect Dynamic schema. The following is a brief description of each option:

  • Authenticated lets you restrict access to the table to only authenticated users. Anonymous access is granted when this option is not selected.
  • Soft delete lets you mark records as deleted instead of removing them from the database. This gives you an option to undelete records. Queries can be filtered to return only active records.
  • Dynamic schema lets you dynamically create new columns on the client instead of the server when new objects are inserted. This is beneficial during development, but a security problem during production usage, so it should be avoided when the app graduates to production.
  • Per-user data adds a user column to the table and lets you filter data based on the current user information. Selecting this option makes sense when authentication is enabled.

When you click Create, Mobile Center will generate a table with a number of system columns, which you can see by selecting the Show system columns switch control or when you click Edit Schema to add your columns, as shown in Figure 2.

The Schema of a New Table, Including System Columns
Figure 2 The Schema of a New Table, Including System Columns

Columns can be of five different types: String, Date, Number, Boolean and Version. Actually, Version is only intended for internal usage with the version column. These types are very flexible because they can receive a variety of platform-specific data types. For instance, in the Microsoft .NET Framework, you can store objects of type Int32 and Double into a column of type Number, and this applies to the other supported development platforms, as well. It’s worth noting that using DateTimeOffset for dates is preferred to using DateTime, as the former includes and takes into account time zone information, whereas the latter does not. Now, click Add Column and add two simple columns: Title and Author (of type String). A popup appears and lets you enter the column name and the data type. Once you’ve added the desired columns, an additional step is required to set column permissions. To accomplish this, you use the options button (an icon with three dots aligned vertically), which provides a menu with several commands. Among the others, the Change Permissions command lets you specify individual permissions for each operation against data, as you can see in Figure 3.

Specifying Permissions for a Table
Figure 3 Specifying Permissions for a Table

Click on Save when ready. It’s worth mentioning that the options menu lets you upload data from .csv files, as well as clear data in the table and delete the table. Another very useful feature is that the page for a table will also show the stored data inside a grid.

Setting Up Authentication

The next step is to set up authentication. In Mobile Center, click the Identity button in the toolbar on the left side of the page. You’ll see the authentication endpoint for Azure Active Directory (Azure AD) and the list of available authentication providers: Azure Active Directory, Microsoft Account, Facebook, Google and Twitter. You can definitely select multiple authentication services, but for this example, use the Microsoft Account service. Whatever authentication service you click, a popup appears showing a link to the documentation for each provider and a list of fields that must be configured based on the selected provider. In the case of the Microsoft Account service, the documentation (available at bit.ly/2peCBgf) explains how to register an app and how to retrieve the app ID and app client secret through the following steps:

  1. Open the Microsoft Account Developer Portal. This is available at apps.dev.microsoft.com. Here, you’ll see a list of apps associated with your Microsoft Account (if any).
  2. Click Add an App.You’ll be asked to specify an app name, which must not include special characters. For the current example, you can enter MyBookshelf. Then, click Create Application.
  3. Generate ID and client secret. When a new app is added, the developer portal generates the Application Id, which is visible in the application page, as shown in Figure 4. You also need a Client Secret, which you obtain by clicking Generate New Password. A popup will show the Client Secret, and this is actually the only time you’ll be able to see it clearly, so copy it into a safe location for later use.
  4. Specify a redirect URI. This is required to tell the authentication service what page it will need to show after the user has supplied the credentials. To accomplish this, click Add Platform, then Web. In the Redirect URIs box you must enter the proper redirect URI, which has the following form: https://mobile-{your-app-id}.azurewebsites.net/.auth/login/­microsoftaccount/callback. Figure 5 demonstrates this step.

Save your changes, go back to Mobile Center and add the Client ID and Client Secret to the configuration page for your app, as shown in Figure 6.

Registering an Application in the Microsoft Developer Portal
Figure 4 Registering an Application in the Microsoft Developer Portal

Entering a Redirect URI
Figure 5 Entering a Redirect URI

Configuring the Microsoft Account Authentication Service
Figure 6 Configuring the Microsoft Account Authentication Service

You can specify additional permissions under Scope, but this is not the case here, so click Save. With a few steps, you’ve successfully configured authentication for your app; similar steps apply to the other authentication providers. Now it’s time to create a cross-platform app and write some code.

Creating and Setting Up a Xamarin Sample Project

In Visual Studio 2017 select File | New | Project. Locate the Cross-Platform node under Visual C# and select the project template called Cross Platform App (Xamarin.Forms or Native). Call the project MyBookshelf and click OK. In the New Cross Platform App dialog, make sure you select the Blank App template, then Xamarin.Forms under UI Technology and Portable Class Library (PCL) under Code Sharing Strategy, and click OK. In order to work against Visual Studio Mobile Center services, including the Mobile Center SDK, you need to download and install the following NuGet packages:

  • Microsoft.Azure.Mobile.Crashes: Enables an app to share crash information with the Mobile Center. It has a dependency on the Microsoft.Azure.Mobile package, which is also installed.
  • Microsoft.Azure.Mobile.Analytics: Enables an app to share usage information with the Mobile Center and has the same dependency on Microsoft.Azure.Mobile.
  • Microsoft.Azure.Mobile.Client: Installs the Azure Mobile Client SDK and lets a Windows or Xamarin app work with the Azure Mobile Apps service.

The next step is modeling objects that map tables in the back-end service.

Defining a Data Model

For better code reuse, you can create a base class that maps the basic structure of a table, and then write derived classes that extend the base object with specific columns. The base class must also implement the INotifyPropertyChanged interface to raise change notification with data binding to the UI. Having said that, you now add to the PCL project a folder called Model and two code files called TableBase.cs and Book.cs. Figure 7 shows the full code for both class definitions.

Figure 7 Defining the Data Model

// Requires the following directives:
// using System.ComponentModel and System.Runtime.CompilerServices
public abstract class TableBase : INotifyPropertyChanged
{
  private string id;
  public string Id
    {
      get
      {
        return id;
      }
      set
      {
        id = value; OnPropertyChanged();
      }
    }
    private string userId;
    public string UserId
    {
      get
      {
        return userId;
      }
      set
      {
        userId = value; OnPropertyChanged();
      }
    }
    private DateTimeOffset createdAt;
    public DateTimeOffset CreatedAt
    {
      get
      {
        return createdAt;
      }
      set
      {
        createdAt = value; OnPropertyChanged();
      }
    }
    private DateTimeOffset updatedAt;
    public DateTimeOffset UpdatedAt
    {
      get
      {
        return updatedAt;
      }
      set
      {
        updatedAt = value; OnPropertyChanged();
      }
    }
    private string version;
    public string Version
    {
      get
      {
        return version;
      }
      set
      {
        version = value; OnPropertyChanged();
      }
    }
    private bool deleted;
    public bool Deleted
    {
      get
      {
        return deleted;
      }
      set
      {
        deleted = value; OnPropertyChanged();
      }
    }
    public TableBase()
    {
      this.CreatedAt = DateTimeOffset.Now;
      this.UpdatedAt = DateTimeOffset.Now;
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
      PropertyChanged?.Invoke(this,
        new PropertyChangedEventArgs(propertyName));
    }
}
public class Book: TableBase
{
    private string author;
    public string Author
    {
      get
      {
        return author;
      }
      set
      {
        author = value; OnPropertyChanged();
      }
    }
    private string title;
    public string Title
    {
      get
      {
        return title;
      }
      set
      {
        title = value; OnPropertyChanged();
      }
    }
}

With this approach, you don’t need to repeat the same common properties for each class; you can simply take advantage of inheritance. In the PCL project, add a code file called Constants.cs, whose content is the following:

public static class Constants
{
  public const string BaseUrl = "https://mobile-{your-app-id}.azurewebsites.net/";
}

This constant will contain the URL of your back-end service and will be used instead of writing the URL manually every time.

Implementing Authentication

The Azure Mobile Client SDK makes authenticating a user very simple. In fact, you just need to invoke the MobileServiceClient.LoginAsync method. LoginAsync takes two arguments: the context in which the authentication UI must be presented and the authentication provider via the MobileServiceAuthentication­Provider enumeration. It returns an object of type MobileService­User, which contains information about the authenticated user. In Xamarin.Forms, the code that authenticates the user can’t be shared in the PCL because iOS and Android manage UI contexts differently. The problem can be solved using the dependency service pattern, therefore adding to the PCL an interface that provides an abstract login method definition, and platform-specific implementations of the interface. In the PCL project, add a new folder called Authentication and an interface called IAuthentication.cs that looks like the following:

using Microsoft.WindowsAzure.MobileServices;
using System.Threading.Tasks;
namespace MyBookshelf.Authentication
{
  public interface IAuthentication
  {
    Task<MobileServiceUser> LoginAsync(MobileServiceClient client,
      MobileServiceAuthenticationProvider provider);
    }
}

This custom definition of LoginAsync takes an instance of the MobileServiceClient class that’s passed by a View Model and that will be used to invoke its LoginAsync method from the platform-specific projects. Add a file called Authentication.cs to both the Android and iOS projects, then look at Figure 8 and Figure 9, which show the Android and iOS implementations, respectively.

Figure 8 Authentication.cs in Android

using System;
using MyBookshelf.Authentication;
using Microsoft.WindowsAzure.MobileServices;
using Xamarin.Forms;
using System.Threading.Tasks;
using MyBookshelf.Droid;
[assembly: Dependency(typeof(Authentication))]
namespace MyBookshelf.Droid
{
  public class Authentication : IAuthentication
  {
    public async Task<MobileServiceUser> LoginAsync(MobileServiceClient client,
      MobileServiceAuthenticationProvider provider)
    {
      try
      {
        var user = await client.LoginAsync(Forms.Context, provider);
        return user;
      }
      catch (Exception)
      {
        return null;
      }
    }
  }
}

Figure 9 Authentication.cs in iOS

using Microsoft.WindowsAzure.MobileServices;
using MyBookshelf.Authentication;
using MyBookshelf.iOS;
using System;
using System.Threading.Tasks;
[assembly: Xamarin.Forms.Dependency(typeof(Authentication))]
namespace MyBookshelf.iOS
{
  public class Authentication : IAuthentication
  {
    public async Task<MobileServiceUser> LoginAsync(MobileServiceClient client,
      MobileServiceAuthenticationProvider provider)
    {
      try
      {
        // Attempt to find root view controller to present authentication page
        var window = UIKit.UIApplication.SharedApplication.KeyWindow;
        var root = window.RootViewController;
        if (root != null)
        {
          var current = root;
          while (current.PresentedViewController != null)
          {
            current = current.PresentedViewController;
          }
          // Login and save user status
          var user = await client.LoginAsync(current, provider);
          return user;
        }
        return null;
      }
      catch (Exception)
      {
        return null;
      }
    }
  }
}

With this approach, each platform-specific project can invoke LoginAsync passing the proper execution context.

Implementing Data Access with the Azure Mobile Client SDK

The MobileServiceClient class also provides everything you need to work with records in a table. You first obtain a reference to a table with the GetTable method, then with methods such as ToEnumerableAync, InsertAsync, UpdateAsync and DeleteAsync, you can query, insert, update and delete records, respectively. These are all generic methods, so you can write a data access layer that can be reused to work with any object that derives from TableBase. Having said that, in the PCL project, add a DataAccess folder and a file called DataManager.cs inside. Before writing the DataManager class, add the following code to the App.xaml.cs file, so that a variable of type DataManager is available at the app level:

internal static DataManager DataManager;
public App()
{
  InitializeComponent();                      
  DataManager = new DataManager(Constants.BaseUrl);
  MainPage = new MyBookshelf.MainPage();
}

Figure 10 shows the code for the DataManager class.

Figure 10 Implementing a Data Access Layer

using Microsoft.WindowsAzure.MobileServices;
using MyBookshelf.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MyBookshelf.DataAccess
{
  public class DataManager
  {
    public MobileServiceClient Client { get; set; }
    public DataManager(string serviceUrl)
    {
      Client = new MobileServiceClient(serviceUrl);
    }
    public async Task SaveAsync<T>(IEnumerable<T> items) where T : TableBase
    {
      var table = this.Client.GetTable<T>();
      foreach (T item in items)
      {
        if (item.Id == null)
        {
          item.Id = Guid.NewGuid().ToString("N");
          await table.InsertAsync(item);
        }
        else
        {
          await table.UpdateAsync(item);
        }
    }
  }
    public async Task<IEnumerable<T>> LoadAsync<T>(string userId)
      where T : TableBase
    {
      var table = this.Client.GetTable<T>();
      var query = await table.Where(t => t.UserId == userId).ToEnumerableAsync();
      return query;
    }
  }
}

In the SaveAsync method, the Id property is used to detect if an item is new or existing. If it’s new, a new GUID is generated and the item is inserted; otherwise, it’s updated. In LoadAsync, the UserId property is used to filter the list of items based on the current user. This is possible because of generics and generic constraints, which let both methods work with any object that derives from TableBase.

The ViewModel

A ViewModel class will be responsible for exposing a collection of books, commands that let you work with Book items and the login logic. Add a new file called BookViewModel.cs into a subfolder called ViewModel in the PCL project, then write the code shown in Figure 11.

Figure 11 Exposing a ViewModel

using Microsoft.WindowsAzure.MobileServices;
using MyBookshelf.Authentication;
using MyBookshelf.Model;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace MyBookshelf.ViewModel
{
  public class BookViewModel : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    private bool isBusy;
    public bool IsBusy
    {
      get
      {
        return isBusy;
      }
      set
      {
        isBusy = value; OnPropertyChanged();
      }
    }
    private bool isUserAuthenticated;
    public bool IsUserAuthenticated
    {
      get
      {
        return isUserAuthenticated;
      }
      set
      {
        isUserAuthenticated = value; OnPropertyChanged();
      }
    }
    private string userId;
    public string UserId
    {
      get
      {
        return userId;
      }
      set
      {
        userId = value; OnPropertyChanged();
      }
    }
    private ObservableCollection<Book> books;
    public ObservableCollection<Book> Books
    {
      get
      {
        return books;
      }
      set
      {
        books = value; OnPropertyChanged();
      }
    }
    private Book selectedBook;
    public Book SelectedBook
    {
      get
      {
        return selectedBook;
      }
      set
      {
        selectedBook = value; OnPropertyChanged();
      }
    }
    public BookViewModel()
    {
      this.Books = new ObservableCollection<Book>();
      this.IsBusy = false;
    }
    public Command SaveBooks
    {
      get
      {
        return new Command(async () =>
        {
          if (IsUserAuthenticated)
          {
            this.IsBusy = true;
            await App.DataManager.SaveAsync(this.Books);
            this.IsBusy = false;
          }
      });
      }
    }
    public Command LoadBooks
    {
      get
      {
        return new Command(async () =>
        {
          if (IsUserAuthenticated)
          {
            this.IsBusy = true;
            var listOfBooks = await App.DataManager.LoadAsync<Book>(UserId);
            this.Books = new ObservableCollection<Book>(listOfBooks);
            this.IsBusy = false;
          }
        });
      }
    }
    public Command AddNewBook
    {
      get
      {
        return new Command(() =>
          this.Books.Add(new Book { UserId = this.UserId }));
      }
    }
    public async Task LoginAsync()
    {
      var authenticator = DependencyService.Get<IAuthentication>();
      var user = await authenticator.LoginAsync(App.DataManager.Client,
        MobileServiceAuthenticationProvider.MicrosoftAccount);
      if (user == null)
      {
        IsUserAuthenticated = false;
        return;
      }
      else
      {
        UserId = user.UserId;
        IsUserAuthenticated = true;
        return;
      }
    }
  }
}

Notice how the LoginAsync method invokes the platform-­specific implementation of the IAuthentication interface via the DependencyService.Get method, passing the active instance of the MobileServiceClient class and the current authentication provider.

The UI

The UI for the sample application is very simple. If a ListView is data-bound to an instance of the ViewModel, an Activity­Indicator will show the progress indicator when the app is busy, and a few buttons are data-bound to commands in the View­Model. The XAML for the UI is shown in Figure 12 and goes in the MainPage.xaml file.

Figure 12 The UI for the Main Page

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="https://xamarin.com/schemas/2014/forms"
  xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:local="clr-namespace:MyBookshelf"
  x:Class="MyBookshelf.MainPage">
  <Grid BindingContext="{Binding}">
    <Grid.RowDefinitions>
      <RowDefinition Height="40"/>
      <RowDefinition Height="30"/>
      <RowDefinition />
      <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <Label Text="My Bookshelf" FontSize="Large" Margin="5"/>
    <ActivityIndicator x:Name="Indicator1" IsRunning="{Binding IsBusy}"
      IsVisible="{Binding IsBusy}" Grid.Row="1"/>
    <ListView HasUnevenRows="True" ItemsSource="{Binding Books}"
      x:Name="BooksListView"
      Grid.Row="2" SelectedItem="{Binding SelectedBook}" >
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
              <ViewCell.View>
               <Frame OutlineColor="Blue">
                 <Grid>
                    <Grid.RowDefinitions>
                      <RowDefinition/>
                      <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Entry Placeholder="Title" Text="{Binding Title}"/>
                    <Entry Placeholder="Author" Text="{Binding Author}"
                  Grid.Row="1"/>
                 </Grid>
               </Frame>
              </ViewCell.View>
            </ViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
   <StackLayout Grid.Row="3" Orientation="Horizontal"
     BindingContext="{Binding}">
     <Button Text="Load" x:Name="LoadButton" Command="{Binding LoadBooks}"/>
     <Button Text="Save" x:Name="SaveButton" Command="{Binding SaveBooks}"/>
     <Button Text="Add" x:Name="AddButton" Command="{Binding AddNewBook}"/>
   </StackLayout>
  </Grid>
</ContentPage>

In the codebehind, you must assign an instance of the ViewModel to the binding context of the page and you’ll need to check that login is necessary every time the user opens the page. Here’s the code:

private BookViewModel ViewModel { get; set; }
public MainPage()
{
  InitializeComponent();
  this.ViewModel = new BookViewModel();
  this.BindingContext = this.ViewModel;
}
protected async override void OnAppearing()
{
  base.OnAppearing();
  if (this.ViewModel.IsUserAuthenticated == false) await this.ViewModel.LoginAsync();
}

LoginAsync is called within the OnAppearing method because this lets you call asynchronous methods at page initialization and every time a page is displayed.

Configuring the App for Analytics and Crash Reporting

With a single line of code, you can configure your Xamarin.Forms app to send usage and crash reports to Visual Studio Mobile Center. In the App.xaml.cs, override the OnStart method as follows:

// Requires using directives for Microsoft.Azure.Mobile,
// Microsoft.Azure.Mobile.Analytics and Microsoft.Azure.Mobile.Crashes
protected override void OnStart()
{
  MobileCenter.Start("android={Your Android App secret here};" +
    "ios={Your iOS App secret here}",
    typeof(Analytics), typeof(Crashes));
}

As you can see, you can enable both the Android and iOS projects by specifying the app secret, which can be found in the Getting Started page of Mobile Center. All the reports can be found in the Analytics and Crashes pages of Mobile Center.

Testing the Application

If you now run the sample app, the first thing you’ll see is the login screen for the Microsoft account. Once you’ve been authenticated, you’ll be able to view, edit and save the list of books, as demonstrated in Figure 13.

The Sample App Running on Android
Figure 13 The Sample App Running on Android

Of course, a similar result will appear on iOS devices. If you try to add and save some items, and then go to the table page in Visual Studio Mobile Center, you’ll see a grid showing your records. Further improvements to the code might involve implementing offline sync with the Azure Mobile Client SDK and more specific error handling in case the user isn’t authenticated.

Wrapping Up

Visual Studio Mobile Center dramatically simplifies the way you implement back-end services for your mobile apps—such as authen­tication and tables—not only with a convenient UI, but also by setting up most of the backing infrastructure on the Azure Mobile Apps service on your behalf. Visit the Mobile Center frequently in order to verify the availability of new features.


Alessandro Del Sole has been a Microsoft MVP since 2008. Awarded MVP of the Year five times, he has authored many books, eBooks, instructional videos and articles about .NET development with Visual Studio. Del Sole works as a senior .NET developer, focusing on .NET and mobile app development, training, and consulting. Follow him on Twitter: @progalex.

Thanks to the following technical expert for reviewing this article: Adrian Hall
Adrian Hall is the Principal Product Manager for Azure Mobile Apps and the mobile backend features within Mobile Center.  Adrian is also a frequent conference speaker, the author of “Develop Cloud Connected Mobile Apps with Xamarin and Microsoft Azure” (available at https://aka.ms/zumobook), a blog and several videos on Azure Mobile Apps.


Discuss this article in the MSDN Magazine forum