August 2015

Volume 30 Number 8

Azure Mobile Services - Azure Mobile Services: A Great Back End for AngularJS

By Jonathan Miller

AngularJS is a great framework for building JavaScript applications for both Web and mobile. It’s very powerful, but it does come with a bit of a learning curve. To get started, I read blogs and books and watched video courses, which are great for learning client-side features, such as forms, routing and validation. Unfortu­nately, the client-side topics always seem to overshadow back-end concerns. Most learning resources barely touch on these at all. One course used the Angular $httpBackend service almost exclusively. $httpBackend is a great way to build fakes for testing, but it isn’t meant for persisting data for a production application. Another resource used an open source product called deployd (deployd.com), which provides a quick and easy way to get a REST/API back-end server up and running. Deployd is free to download and can run on a development machine or server. It’s great for modeling and testing REST APIs. The problem once again is what to do in production. In a production environment, I have to expose a REST/JSON server to the Internet for the AngularJS application to use, but I don’t want to be in the business of hosting and managing servers on the Internet. I need to be able to spin up new applications fast and scale up quickly as needed. I need integrated security without a lot of complexity. I need to be able to set up REST/JSON APIs to store the application data. And, I need all of these issues to be easy to learn and integrate with my application. Luckily, in my research I found that Microsoft has already solved these problems. In this article I’ll show you how to integrate the Azure Mobile Services back end with an AngularJS front end.

Azure Mobile Services (AMS) is really a back end in a box. It brings together all the back-end parts needed for a production app and has a number of compelling features:

  • It provides very fast and redundant cloud storage.
  • It makes building tables that can be accessed via REST/JSON very easy.
  • It provides built-in security and authentication to popular login providers such as Microsoft, Google, Facebook and Twitter.
  • It starts out free and can scale out for high-demand applications.
  • It makes server-side validation easy.
  • It allows for both JavaScript and .NET back ends. Microsoft has made it very easy to provision an AMS site and integrate it with almost any client platform. 

My Angular Notes App

To demonstrate how to connect AngularJS and AMS, I’m going to put together a very simple Angular Notes application. This app will be a single page and will consist of a list of notes. Each note will have a delete button next to it. There will also be a text box for adding a new note to the list. Figure 1 shows what my Angular Notes app will look like.

Angular Notes App
Figure 1 Angular Notes App

For this app, I’ll use Visual Studio 2013 Update 4 and the Azure account I receive with my MSDN benefits. To follow along, first create a new ASP.NET Web Application. Choose the empty template and no options, as shown in Figure 2.

Creating an Empty ASP.NET Project
Figure 2 Creating an Empty ASP.NET Project

Now you should add the AngularJS and Bootstrap libraries, so add the NuGet packages for Angular.Core and Bootstrap.

To create the initial view, add a new HTML page to the root of the project called notes.html. Modify the HTML so it matches Figure 3. Notice that it references Angular and Bootstrap. It also has the ng-app tag, which tells Angular to process this page. Last, it has a body section with an ng-controller tag for the controller I’m going to build later. I’ve sprinkled in some Bootstrap classes to make it look nice. They aren’t required and can be ignored.

Figure 3 Initial HTML View

<html ng-app="notesApp">
<head>
  <title>Angular Notes</title>
  <link type="text/css" rel="stylesheet" href="Content/bootstrap.css" />
  <script src="Scripts/angular.js"></script>
  <script src="notesCtrl.js"></script>
</head>
<body ng-controller="notesCtrl as vm">
  <div class="page-header text-center">
    <h1>
      <span class="glyphicon glyphicon-cloud" aria-hidden="true"></span>
      <span style="padding-bottom:10px">Angular Notes</span>
    </h1>
  </div>
</body>
</html>

To add the list of notes, inside the body section add a new div to the bottom, as shown in Figure 4. This div will loop through the list of notes and display a table row for each. It also puts a delete button on each row. The key tag that makes this work is the ng-repeat tag, which loops through the notes array on the controller.

Figure 4 Adding the List of Notes

<div class="container">
  <div class="panel panel-default">
    <table class="table table-striped">
      <tr class="list-group" ng-repeat="note in vm.notes">
        <td>
          {{note.notetext}}
          <button class="btn btn-xs btn-danger pull-right"
            ng-click="vm.deleteNote(note)">
            <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
          </button>
        </td>
      </tr>
    </table>
  </div>
</div>

Finally, to create a new note box, add one last div to this view so a user can create a new note. Place it above the div for the notes table. In the following code, notice that the input box contents are data-bound to vm.addNoteText and that clicking the button or pressing enter will call the method vm.addNote on the controller:

<div class="input-group" style="padding-bottom:15px">
  <input type="text" class="form-control" ng-model="vm.addNoteText"
    placeholder="new note" ng-keypress="($event.which === 13)?vm.addNote():0" />
  <span class="input-group-btn">
    <button ng-click="vm.addNote()" class="btn btn-success">Add Note</button>
  </span>
</div>

To add the controller, create a new JavaScript file in the root of the project called notesCtrl.js. Figure 5 shows the code for the entire controller. It consists of the initial notes array to be displayed, the addNote function that adds an item to the array, and the deleteNote function that removes a note from the array. Make sure there’s a reference to this script in the notes.html view.

Figure 5 Adding the Controller

angular.module('notesApp', [])
  .controller('notesCtrl', function () {
    var vm = this;
    vm.addNoteText = '';
    vm.notes = [
      { "notetext": "Fix driveway" },
      { "notetext": "Replace roof" },
      { "notetext": "Fix dryer" },
      { "notetext": "Tear out deck" },
      { "notetext": "Add electricity to garage" }
    ];
    vm.addNote = function () {
      if (vm.addNoteText !== '') {
          vm.notes.push({ "notetext": vm.addNoteText });
          vm.addNoteText = '';
      }
    }
    vm.deleteNote = function (note) {
      vm.notes.splice(vm.notes.indexOf(note), 1);
    }
  });

At this point, the core Angular application is done. Running the page displays a list of notes. Clicking the red X next to a note removes it. Typing a new note into the text box and clicking Add Note will add it to the list. So far, however, the list is in memory only. Refreshing the page will bring back the original list, and all the changes will be lost. Let’s move the data storage out of memory and into the cloud.

Storing Data in Azure Mobile Services

I’m going to change the storage mechanism for the notes. Instead of using a static, in-memory array, I’m going to load and save my notes from AMS.

In the Azure Portal, create a new Azure Mobile Service. Make sure it uses the JavaScript back end. Next, click on the Data tab inside the mobile service and then create a new data table as shown in Figure 6.

Creating a New Notes Table
Figure 6 Creating a New Notes Table

Next, to add the note text column, add a string column named notetext to the notes table.

Now you need to get the application key. On the main Azure Portal page of Azure Mobile Services, you’ll see a button labeled Manage Keys. Click this to retrieve the application key and save it somewhere for later. The Angular application will need it to access AMS.

To get AMS working in the Angular app, you need to add two script references to the Notes.html view. The first is for the JavaScript library provided by Microsoft for Azure Mobile Services. The second is an Angular-style service that wraps the Microsoft library. The main benefit of this library is that it extends the Microsoft JavaScript library for AMS and provides Angular-style interfaces and promises. You’ll find excellent sample code for this library on GitHub at bit.ly/1po76vI.

Make sure these new entries appear between the angular.js and the notesCtrl.js references, like so:

<script src="Scripts/angular.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/mobileservices/MobileServices.Web-1.1.2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-azure-mobile-service/1.3.4/angular-azure-mobile-service.min.js"></script>
<script src="notesCtrl.js"></script>

To reference Azure Mobile Services in the controller, change the first line of NotesCtrl.js and add a dependency to ‘azure-­mobile-service.module’:

angular.module('notesApp', ['azure-mobile-service.module'])

Add a constant to the bottom of the notesCtrl.js file with the URL of the Azure mobile site and the application key retrieved earlier. The AMS library will use these to access the AMS site:

angular.module('notesApp').constant('AzureMobileServiceClient', {
  API_URL: "https://angularnotes.azure-mobile.net/",
  API_KEY: "gkwGJioLD3jNxrAX6krXh6jVk6SFkeQr",
});

Now replace the code in the controller that set vm.notes to a static array with data retrieved from AMS. This code retrieves the entire notes table and stuffs the result into the vm.notes array:

Azureservice.query('notes', {})
.then(function (items)
{
  vm.notes = items;
});

Next, change the vm.addNote function so it saves new notes in the notes data table. Once AMS returns that it’s successful, the item is added to the in-memory array. This keeps the application from having to reload the whole list every time something is added to it:

vm.addNote = function () {
  if (vm.addNoteText !== '') {
    Azureservice.insert('notes', {
      "notetext" : vm.addNoteText                 
    }).then(function (newitem) {
      vm.notes.push(newitem);
      vm.addNoteText = '';
    });
  }
}

Finally, change the vm.deleteNote function so it deletes the note from the AMS notes table. Once again, the code waits until AMS succeeds and then deletes it from the in-memory array:

vm.deleteNote = function (note) {
  Azureservice.del('notes', {
    "id": note.id
  }).then(function () {
    vm.notes.splice(vm.notes.indexOf(note), 1);
  });
}

Now all of the notes are retrieved from the notes table in AMS. When a user adds or deletes a note, those operations happen to the data table in AMS. I had to write very little code to achieve this. This is one of the main strengths of AMS—it’s easy to set up and easy to integrate.

Authenticating Users in Azure Mobile Services

Adding authentication to a Web app can be a hassle. There’s always the question of whether to roll your own. These days, unless you really have a compelling case, it almost always makes sense to use one of the major identity providers out there. They can deal with the issues of securely storing passwords and doing resets. AMS makes it easy to connect to the popular identity providers—­Microsoft, Facebook, Twitter and Google. AMS seamlessly integrates authentication and authorization with the logon function and the tables created in AMS. For this article, I’ve chosen to use a Microsoft account for authentication. Once authentication is configured, I’ll change the sample so that only authenticated users can view or edit notes and view their own list.

The first step is to set up your app at the Microsoft Live portal (bit.ly/1JS4jq3). This provides the Client ID and Client Secret that AMS needs to get Microsoft Identity working. Now paste them into the Identity tab in AMS as shown in Figure 7. There’s an excellent article that walks through the process of registering the application at bit.ly/1Ij22hy.

Setting up the Microsoft Identity Provider
Figure 7 Setting up the Microsoft Identity Provider

Next, add login and logout buttons to the view. Add the following div code above the div that contains the notes table:

<div class="text-center">
  <button class="btn btn-primary" ng-if="!vm.isLoggedIn()"
  ng-click="vm.login()">Login</button>
  <button class="btn btn-primary" ng-if="vm.isLoggedIn()"
  ng-click="vm.logout()">Logout</button>
</div>

The ng-if code on the login button makes it so the login button is shown only when the user isn’t logged in. The ng-if code on the logout button makes it so the logout button is shown only when the user is logged in.

Now, add another ng-if tag to the container div to hide the list and the new note text box when the user isn’t logged in. This isn’t a security feature. Security will be enforced by AMS. This just makes the page look appropriate:

<div class="container" ng-if="vm.isLoggedIn()" style="padding:15px">

Next, add the authentication functions to the controller. The isLoggedIn function is used by the view to determine if it should hide or display the login/logout buttons and hide or show the notes list. It just returns the isLoggedIn result from the Azureservice module:

vm.isLoggedIn = function ()
{
  return Azureservice.isLoggedIn();
}

The app’s login function is called when the user clicks the login button. It calls the login function in the Azureservice library. Move the code that queries AMS for the notes list from the top of the controller into this function. Now the list is loaded only after the user authenticates successfully:

vm.login = function () {
  Azureservice.login('microsoftaccount')
  .then(function () {
    Azureservice.query('notes', {})
    .then(function (items) {
      vm.notes = items;
    });
  });
}

The logout function logs the user out of AMS by calling the logout function on the Azureservice module. It also blanks out the notes array:

vm.logout = function () {
  vm.notes = [];
  Azureservice.logout();
}

Right now, the only thing that keeps an unauthenticated user out of the notes list is that the code loads the list only after the user is authenticated. This isn’t secure at all. It’s far better to have AMS enforce this at the back end. In the Azure Portal, open the AMS service and then open the notes table and click on Permissions. Change all of the permissions to Only Authenticated Users as shown in Figure 8. Now any calls to this table will fail if the user isn’t authenticated.

Securing the Notes Table
Figure 8 Securing the Notes Table

Separating User Data

Even though the site authentication is working, all users still share a single list. Let’s make it so each user can view and edit only his own notes. This requires just a few changes in the Azure Portal. I won’t change the Angular app at all.

First, go into the notes data table. Click on columns and add a new string column called userid. This is how I’ll associate a note with a user. Next, go to the script tab on the notes table. Select INSERT from the operation drop-down and add the following to the script:

function insert(item, user, request) {
  item.userid = user.userId;
  request.execute();
}

This new line sets the new row’s userid to the userid from the authentication provider. It’s much more secure to do this in the code on the back end. The code runs in Azure; the user (or attacker) doesn’t have access to it.

To filter the notes returned by userid, select READ from the operation drop-down and change its script:

function read(query, user, request) {
  query.where({ userid: user.userId });
  request.execute();
}

The new query.where line filters the rows returned by the userid column; the logged-in user’s userid is supplied as the value. Filtering the data on the server before it reaches the client is a much more secure method than trying to do it in the client code.

Now the Angular Notes application securely stores notes in Azure Mobile Services. Each user has a separate list of notes that can be accessed only by authenticating first. 

Wrapping Up

With just a small amount of code, this demo application is now cloud-powered with first-class storage and authentication. Don’t be fooled into believing that if you adopt AngularJS on the front end, you have to abandon the Microsoft stack on the back end. AMS integrates with AngularJS seamlessly. Azure Mobile Services is a great back end for AngularJS applications.


Jonathan Miller is a senior architect at CuroGens in Indianapolis. He’s been developing products on the Microsoft stack for a decade and programming on .NET since its inception. Miller is a full-stack product developer with expertise in front-end technologies (Windows Forms, Windows Presentation Foundation, Silverlight, ASP.NET, AngularJS/Bootstrap), Middleware (Windows services, Web API), and back ends (SQL server, Microsoft Azure).

Thanks to the following Microsoft technical experts for reviewing this article: David Crawford and Simon Gurevich
Simon Gurevich is a 15-year Microsoft veteran currently holding a Principal Consultant position in Microsoft Consulting Services, specializing in Azure platform technologies. Over the course of his career Simon has been delivering distributed application architecture and development engagements on Microsoft platform and has been working closely with Azure product group in recent years. Prior to joining Microsoft, Simon had a R&D position in a computer telephony lab where he was developing server-based applications performing high-volume telephony call routing. Simon holds a Master degree in Computer Science and Mathematics.