Skip Navigation LinksHome > View Post

Understanding the pipeline (and sending complex objects into Mobile Services)

In my last post, Going deep with Mobile Services data, we looked at how we could use server scripts to augment the results of a query, even returning a hierarchy of objects. This time, let us explore some trickery to do the same, but in reverse.

Imagine we want to post up a series of objects, maybe comments, all at once and process them in a single script… here’s a (somewhat manufactured scenario) demonstrating how you can do this. But first, we’ll need to understand a little more about the way data is handled in Mobile Services.

image

If you think of the Mobile Service data API as a pipeline, there are two key stages: scripting and storage. You write scripts that can intercept writes and reads to storage. There are two additional layers to consider:

  1. Pre-scripting
    This is where Mobile Services performs the authentication checks and validates that the payload makes sense – we’ll talk about this in more detail below.
  2. Pre-Storage
    At this point, we have to make sure that anything you’re about to do makes sense – this validation layer is much stricter and won’t allow complex objects through. This stage is also where we handle and log any nasty errors (to help you diagnose issues) and perform dynamic schematization.

The pre-scripting layer (1) expects a single JSON object (no arrays) and if the operation is an update (PATCH) and has an id specified in the JSON body – that id must match the id specified on the url, e.g. http://yourapp.azure-mobile.net/tables/foo/63

But with that knowledge in mind, we can still use the scripting layer to perform some trickery, if you so desire, and go to work on that JSON payload however it sees fit. Take the following example server script; it expects a JSON body like this:

{
    ratings: [
        {
            movieId: 10,
            rating: 5
        },
        {
            movieId: 63,
            rating: 2
        }
] }

A body, with a single ‘ratings’ property that contains an array of ratings.

function insert(item, user, request) {
    // TODO - perform any validation and security checks
    var ratingsTable = tables.getTable('ratings');
    var ratings = item.ratings;
    var ids = new Array(ratings.length);
    var count = 0;
    ratings.forEach(function(rating, index) {
        ratingsTable.insert(rating, {
            success: function() {
                // keep a count of callbacks
                count++;
                // build a list of new ids - make sure
//
they go back in the right order ids[index] = rating.id; if (ratings.length === count) { // we've finished all updates,
//
send response with new IDs request.respond(201, { ratingIds: ids }); } } }); }); }

Sending the correct payload from Fiddler is easy, just POST the above JSON body to http://yourapp.azure-mobile.net/tables/ratings and watch the script unfold the results for you. You should get a response as follows:

HTTP/1.1 201 Created
Content-Type: application/json


Content-Length: 19

{"ratingIds":[7,8]}

Which is pretty cool – Mobile Services really does present a great way of building data focused JSON APIs. But what about uploading data like this using the MobileServiceClient in both C# and JS?

C# Client

The C# client is a little trickier. You’re probably using types and have a Rating class that has a MovieId and Rating property. If you have an IMobileServiceTable<Rating> then you can’t ‘insert’ a List<Rating> it simply won’t compile. In this case, you’ll want to drop to the JSON version of the client – it’s still really easy to use.

// Source data
List<UserRating> ratings = new List<UserRating>()
{
    new UserRating { MovieId = 5, Rating = 2 },
    new UserRating { MovieId = 45, Rating = 7 }
};

// convert to an array in JSON
JsonArray arr = new JsonArray();
foreach (var rating in ratings)
{
    arr.Add(MobileServiceTableSerializer.Serialize(rating));
}

// Now create a JSON body
JsonObject body = new JsonObject();
body.Add("ratings", arr);

// insert!
IJsonValue response = await MobileService.
GetTable("ratings").InsertAsync(body); // the whole hog - process results and
// attach the new Ids to objects
var inserted =
response.GetObject()["ratingIds"].GetArray(); for (var i = 0; i < inserted.Count; i++) { ratings[i].Id = Convert.ToInt32(
inserted[i].GetNumber()); }

If you were doing this a lot, you’d probably want to create a few helper methods to help you with the creation of the JSON, but otherwise, it’s pretty straightforward. Naturally, JavaScript has a slightly easier time with JSON:

JS Client

// data source
var ratings = [{ movieId: 1, rating: 5 }, 
{ movieId: 2, rating: 4 }]; // insert! client.getTable("ratings").insert({ ratings: ratings }).done(function (result) { // map the result ids onto the source for (var i = 0; i < result.ratingIds.length; i++) { ratings[i].id = result.ratingIds[i]; } });

Nice!

If this feels like too much work, don’t worry, we’re working on making it even easier to build any API you like in Mobile Services. Stay tuned!

 
Josh Post By Josh Twist
6:34 AM
10 Sep 2012

» Next Post: Making HTTP requests from Scripts in Mobile Services
« Previous Post: Going deep with Mobile Services data

Comments are closed for this post.

Posted by Russell Archer @ 10 Sep 2012 2:04 PM
Really excellent post! And a great series on Azure mobile services - thanks!

Posted by josh @ 10 Sep 2012 4:20 PM
Thanks Russell!

© 2005 - 2014 Josh Twist - All Rights Reserved.