Share via



November 2015

Volume 30 Number 12

Data Points - Aurelia Meets DocumentDB: A Matchmaker’s Journey

By Julie Lerman | November 2015

Julie LermanIn the past months you’ve seen, via this column, my explorations into worlds unknown. My September column delved into data binding in an upstart JavaScript client framework called Aurelia, which communicated with a back-end ASP.NET 5 Web API to retrieve and store data. That Web API was using SQL Server and Entity Framework behind the scenes. My June column explored the new Microsoft Azure NoSQL database service, DocumentDB. In that column I also built an ASP.NET MVC 5 Web API, but that Web API leveraged the DocumentDB .NET client library to communicate with a DocumentDB database.

With the wheels greased for Aurelia and DocumentDB, I wanted to put those two together. I headed down some bumpy roads and hit some walls, but eventually wound up on the correct path to allow Aurelia to communicate with DocumentDB. In this column, I’ll share some of the lessons I learned along the way and an overview of my final solution. In an upcoming column, I’ll provide more detail about that solution.

While you’ll certainly learn a lot from the solution I eventually came up with, I think the steps I took along the way, even those that led to failure, are equally educational.

I’ll begin by sharing my plan—which originated in a vacuum of inexperience with JavaScript and its many APIs, tools and patterns—then reveal what seemed at the time like great ways to achieve my goal. If I instead went straight to the correct path, chances are you’d second guess my choice and try to find a better way, only to arrive at the same dead-ends I’ve already visited. Then, of course, I’ll share with you the true path, although it takes more than a single installment of this column to tell the whole story.

Best Laid Plans: “How Hard Can It Be?”

Azure DocumentDB is a service, and raw interaction with it is through either a SQL syntax or RESTful HTTP calls. In the previous column, rather than work at that low level, I took advantage of one of the many APIs that Microsoft has created for DocumentDB—the .NET API. This allowed me to use LINQ to express and execute queries against my database, such as:

return Client.CreateDocumentQuery(Collection.DocumentsLink)
       .Where(d => d.Id == id)
       .AsEnumerable()
       .FirstOrDefault();

I wrote a Web API to do this work for me.

In the demo for my column on Aurelia data binding, I was able to easily make HTTP calls to a different Web API, one that used Entity Framework to hit a SQL Server database. I could’ve just replaced that Web API with the one I had built to talk to DocumentDB. And in that scenario, my job would be done and this column would be the shortest one by me you’ve ever read. How boring.

Instead, I thought it would be more interesting to use the direct REST interaction that DocumentDB provides. It seemed simple enough. The DocumentDB documentation shows quite a few examples of HTTP requests made to DocumentDB, which I thought I’d be able to leverage. Figure 1 shows one example.

Figure 1 An Example HTTP Request to DocumentDB

POST https://contosomarketing.documents.azure.com/dbs/XP0mAA==/colls/XP0mAJ3H-AA=/docs HTTP/1.1
x-ms-DocumentDB-isquery: True
x-ms-date: Mon, 18 Apr 2015 13:05:49 GMT
authorization: type%3dmaster%26ver%3d1.0%26sig[A HASH GOES HERE]
x-ms-version: 2015-04-08
Accept: application/json
Content-Type: application/query+json
Host: contosomarketing.documents.azure.com
Content-Length: 50
{
 query: "SELECT * FROM root WHERE (root.Author.id = 'Don')",
 parameters: []
}

But it’s not quite so easy. To start, the master key, which you see in the authorization, isn’t something you want to provide inside a client application. Furthermore, it isn’t truly the master key that comes from DocumentDB settings in the Azure portal; it’s a hash of the key plus additional information. The “Access Control on DocumentDB Resources” article at bit.ly/1O9dBfP describes how to construct this string, but even this didn’t enable me to test these API calls in Fiddler.

But the bigger problem is that I wouldn’t be doing this in the client application, anyway. The recommended architecture according to “Securing Access to DocumentDB Data” (bit.ly/1N2ZiuF) is to create middleware that has safe access to your master key and is able to generate and return resource keys for a client-side application to use.

So I did that. I built an ASP.NET Web API using the .NET client for DocumentDB to return a properly composed resource key on demand. This entailed all of the same setup code that was part of my earlier DocumentDB column, where I defined my Azure account, the database client, the database within that client and the collections within that database. On top of that I had an 85-line controller that connected to the database; checked for a user; checked for, cleared out and recreated permissions for that user for the action I was about to perform; then generated, hashed and returned a resource token to the requesting client. That was a pretty complicated bit of code to comprehend and set up.

With that service in place, my next step was to have my Aurelia app call that service to retrieve a token for a given operation and then reuse that token in that operation. This isn’t much different in the long run than security operations we use, for example, for Windows Communication Foundation (WCF) services. But it made for a very, very chatty solution. And, in the end, I still was unable to construct a proper request with my generated resource tokens on the client side (JavaScript) because there were more complexities required by DocumentDB. DocumentDB refused to authorize my requests to retrieve data. So I decided that making my own RESTful calls directly from a client app via HTTP to my DocumentDB was a path that wasn’t going to lead to success. I do, however, anticipate that as DocumentDB evolves, so will our options for connecting to it, and I plan to revisit this idea in the future.

Still, all was not lost. DocumentDB also has a JavaScript SDK. This SDK would know how to construct the RESTful calls to DocumentDB on my behalf even if I was using its higher-level methods. I brought the SDK into my client solution with the understanding that I could let it construct the request for me using resource tokens requested from my ResourceTokenGenerator Web API. This felt like the right path, finally, but in the end I hit yet another wall: There was no way to enable cross-origin resource sharing (CORS), which meant that calls from my client-side app on one domain to my service on another would not be allowed.

At this point, having exhausted my resources and my curiosity about making RESTful calls without a wrapper to do it for me, and still not wanting to just flip to my existing Web API to get my Aurelia app to talk to DocumentDB, I headed down another road.

Success: DocumentDB, Express, Aurelia and Node.js

In addition to the. NET and JavaScript client SDKs, DocumentDB also provides a Node.js SDK (bit.ly/1LifOa1). This lets you use Node.js, a JavaScript implementation that works on the server side—much like ASP.NET code-behind logic—to easily access DocumentDB. All of the hard parts of configuration, authentication and building the RESTful API calls are wrapped into methods of the SDK. So I decided this was the path I’d have to follow to let my Aurelia application talk to DocumentDB. It meant a lot of new learning hurdles for me. I’d never touched Node.js and am famously a JavaScript noob; moreover, it involved an additional API, Express, which wraps up a bunch of core functionality to make it easier to use Node.js. But that’s not all. For my first dive into Aurelia, I had to get used to working at the command line and using SublimeText, a text editor that’s much savvier for Web development than Notepad. Because most of the action in that earlier app was on the client side, I was able to debug right in the browser. But now I was debugging Node.js code, which is on the server. It turned out that the new addition to the Visual Studio family, Visual Studio Code, is a great tool for that.

Thankfully, I was able to benefit from two key samples. On the DocumentDB side, there’s a walk-through for building a small Web application with Node.js and DocumentDB (bit.ly/1FljQs6). On the Aurelia side, there’s a repository on GitHub that sets up a skeleton Aurelia app with Node.js server-side logic already integrated (bit.ly/1XkMuEX).

In order to implement my solution, it was critical to have a good understanding of the underlying mechanics of the sample that uses the Node.js SDK. I’ll spend the rest of this column exposing details beyond what the high-level walk-through provides. This will set you up for the reveal of how I wired up the API in my final solution.

The DocumentDB Node.js walk-through provides back-end logic in Node.js that leverages the DocumentDB Node.js SDK to communicate with DocumentDB. The first chunk of this logic is a pair of generic utilities that takes care of creating an instance of the database connection, creating the database first if necessary, and creating an instance of the specific collection within the database with which to work. These utilities can be reused in other applications to communicate with any DocumentDB because DocumentDB allows you to pass in authentication information and other information to specify the database and collections with which you’re working.

This utilities class starts by making a reference to the DocumentDB SDK for Node.js that has already been installed into the solution:

var DocumentDBClient = require('DocumentDB').DocumentClient;

It then sets up the methods that take in the relevant connection information as parameters. Here, for example, is the class declaration with the beginning of the getOrCreateDatabase method, which first defines a query to get the database from Azure, then uses the queryDatabases method of the SDK DocumentClient class to execute that query. If the results are empty, then another call (not shown) will create the database for you. The database instance is returned from the method. You can see the full listing of the DocDBUtils class in the referenced article (bit.ly/1FljQs6):

var DocDBUtils = {
 getOrCreateDatabase: function (client, databaseId, callback) {
  var querySpec = {
   query: 'SELECT * FROM root r WHERE r.id=@id',
   parameters: [{
    name: '@id',
    value: databaseId
   }]
  };
  client.queryDatabases(querySpec).toArray(function (err, results) {
  // Additional logic to specify callbacks and more

The second chunk of logic, in a file called tasklist.js, is akin to a controller. It offers methods to leverage the database and collection instances provided by the DocDBUtils class so you can interact with the data. This controller is designed specifically for the sample that stores and retrieves ToDo items—Tasks. The Task object is encapsulated in a class called TaskDao, and you’ll see references to an instance of TaskDao in the controller class. The controller has methods to retrieve Tasks, as well as to add new ones, and to update and delete. The class begins with references to the DocumentDB SDK, as well as the utility class I’ve just described:

var DocumentDBClient = require('DocumentDB').DocumentClient;
var docdbUtils = require('./docdbUtils');

Tasklist.js includes functions such as showTasks and addTask. These functions follow Node.js conventions by taking as parameters a request object and a response object that allow Node.js to either pass the request from the browser along to another process or inject whatever it wants into the response, which will get passed back to the browser. Figure 2 displays the showTasks function.

Figure 2 The showTasks Command in the tasklist.js Controller Class

showTasks: function (request, response) {
 var self = this;
 var querySpec = {
  query: 'SELECT * FROM root r WHERE r.completed=@completed',
  parameters: [{
   name: '@completed',
   value: false
  }]
 };
 self.taskDao.find(querySpec, function (err, items) {
  if (err) {
   throw (err);
  }
  response.render('index', {
   title: 'My ToDo List ',
   tasks: items
  });
 });
},

Keep in mind that there’s one additional library—Express—being used in this sample. Express wraps Node.js features into higher-level methods. Notice that the showTasks function uses an Express render method of the response object to render the index view (such as index.html), passing the items retrieved from DocumentDB into the tasks property that will be available to use in the Index.html file.

The controller (the TaskList class) is the first entry point into the server-side Node.js logic as it responds to a Web site’s routing. The logic in the controller methods uses the taskDAO object to trigger queries and updates as shown by the call to self.taskDao.find in the showTasks function. taskDAO has an init function that uses the DocDbUtils to set up the database and collection to be used. With those in hand, it can then use the DocumentDB SDK directly to define and execute the queries and updates in its find, getitem and updateItem functions, as Figure 3 shows.

Workflow Dependencies of the DocumentDb Node.js Sample Application Classes and SDK
Figure 3 Workflow Dependencies of the DocumentDb Node.js Sample Application Classes and SDK

With the back-end logic set up in Node.js, the next step is to build the front end. The walk-through on the DocumentDB site uses a view-generation framework called Jade. With HTML files for views and routing set up using the Jade API, the UI is able to respond to user navigation requests by calling into the taskList controller on the server, where I can safely store my DocumentDB keys to authorize my interactions with the data.

Next Steps: Hooking Up Aurelia to the Node.js Back End

Remember, though, that my goal was to use Aurelia as the client framework, not Jade. What came next was taking the lessons about using the DocumentDB Node.js SDK and applying them to the Node.js-enabled skeleton application provided by the Aurelia-node sample on GitHub. Aurelia routing works a bit differently from Jade routing, however, and it wasn’t just a matter of “clicking” these two puzzle pieces together. My inexperience with Node.js and Express, together with my general “knows-enough-to-be-dangerous” JavaScript skills made the challenge much greater than it needed to be. But I did eventually work it all out with help from a number of the Aurelia core team members.

In my next column I’ll walk you through the critical connectors between the controller and the Aurelia routing and show how using the server-side Node.js solution to interact with my DocumentDB compared to the simplicity of making direct HTTP calls from Aurelia to a Web API.


Julie Lerman is a Microsoft MVP, .NET mentor and consultant who lives in the hills of Vermont. You can find her presenting on data access and other .NET topics at user groups and conferences around the world. She blogs at thedatafarm.com/blog and is the author of “Programming Entity Framework” (2010), as well as a Code First edition (2011) and a DbContext edition (2012), all from O’Reilly Media. Follow her on Twitter: @julielerman and see her Pluralsight courses at juliel.me/PS-Videos.

Thanks to the following technical experts for reviewing this article: Ryan CrawCour and Patrick Walters
Ryan CrawCour is 20-year database veteran who started out many years ago writing his first stored procedure for SQL Server 4.2. Many cursors, joins and stored procedures later he began exploring the exciting free world of NoSQL solutions.

Patrick Walters has been a part of the great community of Aurelia developers who enjoys offering an ear to questions on the official Aurelia gitter channel.