Azure Mobile Apps and NodeJS

Microsoft has just open sourced the Azure Mobile Apps SDK for Node. One of the promises of Azure App Service was the ability to throw together apps that serve the web and mobile community simultaneously and to do it quickly. This capability has been available with the .NET crowd for a while. With the release of the Azure mobile Apps SDK for Node, it’s available to Node programmers too.

The SDK is built on top of ExpressJS – a very well-known and respected web service. This means you can develop your web application using all the power of the ExpressJS platform, then add the Mobile Apps piece. I’m writing a Single page application, so my entire app is in a static area. Let’s take a look pre-Mobile Apps work (written in ES6):

///<summary>
/// A basic web server based on ExpressJS that serves up static content
///</summary>

import express from 'express';
import http from 'http';
import morgan from 'morgan';
import staticFiles from 'serve-static';
import {extractAuthSettings} from './utils';

var service = express();
// HTTP Port is set by PORT in Azure
var httpPort = process.env.PORT || 3000;

// Morgan is a logging service - https://github.com/expressjs/morgan
// NODE_ENV === 'production' on Azure
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
  service.use(morgan('dev'));
}

// Serve up files from a static area - we are a SPA
service.use(staticFiles('./wwwroot'));

service.get('/api/settings', (req, res) => {
  try {
    let settings = {
      auth: extractAuthSettings()
    };

    res.set('Content-Type', 'application/json');
    res.status(200).send(settings);

  } catch (err) {
    // If there was an error, then return 404
    res.status(404).send(err.message);
  }
});

// This code actually listens on the specified port.  Uses the PORT
// environment variable to determine the TCP port to listen on.
http.createServer(service).listen(httpPort, err => {
  if (err) {
    console.error(`Error listening to port ${httpPort}: ${err.code}`);
  } else {
    console.info(`Listening on port ${httpPort}`);
  }
});

This code does two things for me – first, it serves up the contents of ./wwwroot as static files. I have a whole build process for handling this, since my application is ES6, React and Flux based. I’ve also got a single API called /api/settings that returns any settings I need. Since I store my authentication settings in the App Settings section of Azure (and environment variables when I’m developing locally), I have a function for creating the object.

Now, let’s add an API for serving up database tables. We’ll use the Azure Mobile Apps SDK for Node for this. First off, load up the API:

npm install --save Azure/azure-mobile-apps-node

Yes, it’s so new it doesn’t have an npm entry yet. That will come in due course. The SDK is only in preview right now, so it could materially change before release.

Now that I have the SDK installed in my project, the code needed to add a simple table controller is just four lines. At the top of the file, I import the SDK:

import express from 'express';
import http from 'http';
import morgan from 'morgan';
import staticFiles from 'serve-static';
import {extractAuthSettings} from './utils';
import azureMobileApp from 'azure-mobile-apps';

Right before I start listening for connections, I do the following:

// Create a new Azure Mobile App
var mobileApp = azureMobileApp();

// Define the tables we are going to expose
mobileApp.tables.add('GWCharacters');

// Attach the app to the Express instance
mobileApp.attach(service);

This provides a simple API on /tables/GWCharacters. You can get the table which will return a list of all the entries, plus you get individual record CRUD operations:

  • C = Create = POST a new entry
  • R = Retrieve = GET an ID
  • U = Update = PATCH an existing entry
  • D = Delete = DELETE an existing entry

These operations are designed to be mobile offline-sync friendly. That means you can use one of the client SDKs for Azure Mobile Apps and utilize this same API.

Databases

By default the SDK uses the Azure SQL Database. It will pick up on the appropriate Connection String when you create the Azure SQL Database – I’ve blogged about that before. However, during development you will likely want to use a local database. Even though Visual Studio comes with SQL Express, it’s generally best to install from the install media so that you can get access to the SQL Server tools like Configuration Manager. This will ease your administrative burden in getting it set up. You can download the SQL Server 2014 Express Edition from Microsoft. Make sure you download SQL Server 2014 Express with Tools.

If you are going to be testing and developing by deploying to Azure, then you don’t need to do this.

Once installed, you will want to configure the following:

  1. TCP Port Enabled
  2. A new database
  3. Username and Password for access

These pieces will also be used to formulate the Connection String I need for the local version of the database. Once you have the SQL Server 2014 Express installed, start SQL Server Configuration Manager. Expand the SQL Server Network Configuration and then double-click on the Protocols for SQLEXPRESS:

sqlexpress-config

Right click on the TCP/IP and select Properties, then select the IP Addresses tab:

sqlexpress-config-2

For each entry, set the TCP Port to 1433. If you don’t want to set them all, then make sure you set the entry for 127.0.0.1 and IPAll. Once this is done, click on OK. Then right-click on the TCP/IP protocol again and select Enable. It will prompt you to say that you need to restart the service. To do this, select SQL Server Services in the left hand tree. Highlight the SQL Server. Right-click and select Restart.

The new user and database are handled in a different tool – the SQL Server Management Studio. Connect to the local instance (it’s the default connection most of the time). Right-click on Databases and select New Database.... Enter a name (mine is grumpy-wizards), then click on OK.

To create a username and password, expand Security, then Logins – you will note that a bunch of logins are created by default. Right-click on the Logins node and select New Login.... Enter a suitable login name (I used gw_access), select SQL Server Authentication and enter a password. It’s a good idea to uncheck the User must change password at next login and Enforce password expiration boxes – this is a test scenario, after all. Select the database you created as the default database. Then click on OK.

This doesn’t provide the user with access to the grumpy-wizards database. Right-click on the login ID (in the Security -> Logins node) and select Properties. Go into the User Mapping area and map the grumpy-wizards database. Select dbo as the Default Schema and ensure the user has db_owner and db_datawriter role membership checked:

sqlexpress-config-3

You need the ability to create tables within the database. Under normal circumstances, you would use fine grained controls, granting the CREATE TABLE and ALTER SCHEMA permissions only within grumpy-wizards. However, this is a test database – not the production database. I generally give more permissions in development.

A final piece needs to be done. Right click on the server and select Properties, then Security. Under Server Authentication, check that the mode is SQL Server and Windows Authentication mode. If you don’t have this selected, then your user won’t be able to log in. If you change it, click on OK, then right-click on the server again and select Restart.

Once all this is done, you can construct a connection string for test purposes. Here is mine:

$env:SQLCONNSTR_MS_TableConnectionString = "Data Source=127.0.0.1; Database=grumpy-wizards; User Id=gw_access; Password=YourPassword; MultipleActiveResultSets=true;"

Phew! Fortunately, this is a one time activity for your app. For testing, I recommend downloading Postman – you can send the URI localhost:3000/tables/GWCharacters:

sqlexpress-postman

This is the GET ALL RECORDS request. We currently don’t have any responses. Let’s do a POST of some new data:

sqlexpress-postman-2

When sending the body, change the application type to JSON (application/json). If you don’t, the table controller won’t realize it has to decode the text before applying it to the database. It will create the record but without content.

I can now GET localhost:3000/tables/GWCharacters/e094bf05-ea52-484d-b5f5-c25542e00562 to get the record details. This URI is based on the id of the record. Also note the fields with a double-underscore – these are added by the SDK to support Offline Sync and Soft Delete. If you flip over to the Headers, you will notice an ETag. This allows you to implement caching and only returning entries that have changed.

This isn’t ideal. There are a number of things I want to do here. Firstly, GWCharacters isn’t the only table I want to produce. Adding additional tables is trivial – just add more tables to the mobileApp variable. I also want to define the acceptable fields in configuration and link in authentication by utilizing the social authentication from the client that I have already implemented.

However, first pass – I have a Mobile API that I can use from my client code. You can download the Azure Mobile Apps SDK from their GitHub repository.

Node, MVC Controllers and ECMAScript 2015

Long time readers of my blog will remember that I previously covered Node and MVC applications in a short tutorial series. At that point, I wrote the controllers and loader in ECMAScript 5.1. The code to load the controllers was this:

  fs.readdirSync("./controllers").forEach(function (file) {
    if (file.substr(-3) === ".js") {
      console.info("Loading Controller " + file);
      var base = "/" + path.basename(file, ".js");
      var route = require("./controllers/" + file);
      app.use(base, route);
    }
  });

The typical controller looked like this:

"use strict";

var express = require("express"),
    path = require("path"),
    config = require("../config.json"),
    extend = require("extend");

var router = express.Router(), // eslint-disable-line new-cap
    controller = path.basename(__filename, ".js"),
    loginRoute = config.loginRoute || "/account/login";

/**
 * Set of default properties for the rendering engine
 */
function defaultProperties(req) {
  return {
    title: "Unknown",   // Default title in case the developer doesn't set one
    user: req.user
  };
}

/**
 * Render an appropriate view
 */
function view(req, res, viewName, locals) {
  res.render(controller + "/" + viewName + ".html",
    extend({}, defaultProperties(req), locals));
}

/**
 * GET /{controller=Home}/index
 */
function index(req, res) {
  if (!req.isAuthenticated()) {
    res.redirect(loginRoute);
    return;
  }
  view(req, res, "index", { title: "Home" });
}

// Per-route functionality
router.get("/index", index);

// Default route is to GET index
router.get("/", index);

module.exports = router;

That’s a lot of boilerplate code and it’s completely unreadable for mere mortals. I am working on learning ECMAScript 2015 in depth and I thought I would re-visit this topic. Could I make my controller modules into classes and simplify the whole controller configuration?

Step 1: The New Controller Loader

Since my controllers are going to be classes, I knew I was going to need to adjust the loader. My aim here is just to load the controller classes; not to get the perfect class loader. Here is my code:

// MVC Controllers
var controllerList = {};
fs.readdirSync(path.join(__dirname, "controllers")).forEach(function (file) {
	if (file.substr(-3) === ".js") {
		var basePath = path.basename(file, ".js");
		var Controller = require(`./controllers/${file}`);
		controllerList[basePath] = new Controller(basePath);
		app.use(`/${basePath}`, controllerList[basePath].router);
	}
});

This code loops through every single JavaScript file in the controllers directory. For each one, it constructs a basePath. If the controller is called home.js, then the basePath becomes “home”. I then load the javascript file using a standard “require” statement. Since it’s a class, I create a new object passing in the basePath. I expect that object to expose a router parameter and I use that to link in the router to the basePath. I construct the path using an ES6 template string.

Step 2: The Controller – First Pass

One of the concepts I am pretty religious about is this: Don’t over-complicate the solution early. Get it working, then see if you can do something to make the solution simpler, easy to test, read better, more efficient or whatever you want to do. Here is my first controller:

var express = require("express"),
	extend = require("extend");

export default class HomeController {
	constructor(basePath) {
		this.basePath = basePath;
		this.router = express.Router(); //eslint-disable-line new-cap

		// Route definitions for this controller
		this.router.get("/", (req, res) => { this.index(req, res); });
		this.router.get("/index", (req, res) => { this.index(req, res); });
	}

	renderView(response, viewName, localData = {}) {
		let viewPath = this.basePath + "/" + viewName;
		let defaultData = {
			title: "~~~Unknown~~~"
		};
		let data = extend(defaultData, localData);
		response.render(viewPath, data);
	}

	// GET /home/index (or just /home)
	index(request, response) {
		this.renderView(response, "index");
	}
}

One of the things you will note is that this actually has a lot in common with the ECMAScript5 version of the same controller – it’s just in class form. My module exports the controller class by default. That means I can import it with whatever name I want. The constructor stores the base path that it is passed and creates a new router. The constructor also constructs the routes available in the controller. It uses ES6 fat arrows to preserve the “this” variable.

The renderView method combines a dataset with a view and renders a view. Note I’m using ES6 default parameters and the block-level “let” statement – more ES6 features in use.

Finally, I have a method that actually handles a route. Really, the only unique things for this controller are the index() method that handles a route and the route definition in the constructor.

Step 3: Simplify the Code

This controller class actually works, but I can see a bunch of duplicated code. In the constructor, the basePath and router will always be done this way. I’m allowing the underlying system access to the router variable – definitely not what I want. I want the router to be read-only after creation. Also, the renderView() method is going to be boiler plate code – I want to abstract that away. My simplifying thought here is this: let’s create a Controller class with all the common code in it. We can then extend the Controller class to create the HomeController and only include the “differences”. Here is my new Controller.js file:

var express = require("express"),
	extend = require("extend");

export class Controller {
	constructor(basePath) {
		this.prvBase = basePath;
		this.prvRouter = express.Router(); //eslint-disable-line new-cap
	}

	renderView(response, viewName, localData = {}) {
		let viewPath = this.prvBase + "/" + viewName;
		let defaultData = {
			title: "~~~Unknown~~~"
		};
		let data = extend(defaultData, localData);
		response.render(viewPath, data);
	}

	get basePath() {
		return this.prvBase;
	}

	get router() {
		return this.prvRouter;
	}
}

A lot of this code comes from the original home.js code. I’ve converted the basePath and router variables into ES6 getters so that I can make them read-only (assuming one uses the published API). Now, what does an implementation of a controller look like? Let’s look at the new home.js:

import {Controller} from "../mvc/Controller";

export default class HomeController extends Controller {
	constructor(basePath) {
		super(basePath);

		// Route definitions for this controller
		this.router.get("/", (req, res) => { this.index(req, res); });
		this.router.get("/index", (req, res) => { this.index(req, res); });
	}

	index(request, response) {
		this.renderView(response, "index");
	}
}

This is getting much closer to where I want to be. The super() call is for running the constructor of the class I am extending, thus setting up the common code. I still have to define the routes within the constructor, but I don’t have any boiler-plate code.

What else would make this controller object awesome? ECMAScript 7 is defining a concept called decorators. With ES7 decorators, I could theoretically do something like this:

export default class HomeController extends Controller {
    @HttpGet([ "/", "/index" ])
    index(request, response) {
        this.renderView(response, "index");
    }
}

Of course, ES2015 (also known as ES6) is just out and I don’t expect ES7 to be ratified for a number of years, so there is no guarantee that anyone will support ES7 decorators. You can check out the compatibility chart at Kangax. Note that only Babel supports ES7 decorators right now.

I’m going to delve into decorators in another blog post. For now, this mechanism is great for developing an MVC application without the need of libraries beyond the standard ExpressJS.