Wednesday, October 10, 2012

My experiments with Windows Azure Mobile Services – Part I


In August, Microsoft released a new Azure service called Windows Azure Mobile Services. These services, make developing windows store apps easier. If you haven’t started taking a look at it, you can start here.  If you are thinking about using them in your app, you have to be aware of the fact that the javascript client and the server side client versions have some differences.

While most of the fundamentals are the same, I believe the C# version of the Mobile Services Client is a bit more comprehensive than the Javascript version. This being the first version, I am hoping they are going to have the same features across both the clients.

This post deals with using the client in javascript apps. I am not going to go into the details of how to get it working. There is a lot of literature out there that covers this. In short, you download the extension for javascript, get your app key from the portal and use the client library to make calls to the service.

This works very well. With a couple of lines of code, you get your data to the app. But, I was wary of leaving the app key in the client machine. I also want all my business rules in the service not in the client app.

So I was looking to access the Mobile Services from a service.Also, my app already talks to a service that I host on azure, so I wanted all logic to be on the service not on the client. Unfortunately, you can’t use the client library in a WCF Service project.  So I decided to figure out how to call the Mobile Services from a service.

At the backend, the Mobile Services client library just calls a REST API. You can see this by stepping through the code in MobileServices.js. The code that actually makes the call is

   1: Platform.webRequest(options, handler);

Once I figured that out, I decided to write code in my service that does the same.

Let me give you some context  about what my app does. The app allows users to rate movies. It talks to an external webservice to get the list of movies and stores the ratings in Azure Mobile Web Services table. My Azure Mobile Service table structure is shown below


The MovieId stores the movie id from the external service and the Value column stores the ratings of the movie. This is the table I am going to query from my service.


I created the classes above to do this. A brief description of the classes before we delve into the code within each of them

AzureMobileTable – This loosely represents an Azure Mobile Services Table. I say loosely because,  the methods here are not present in Azure Mobile Services. These will be translated into REST URIs  as you will shortly see.

AzureMovieBroker – This acts as the broker between the WCF service and Azure Mobile Services. This will implement the methods that are needed by the app.

AzureMobileHelper – This is the helper class that runs the methods on Azure Mobile Services. i.e. Makes the REST call. The helper class always executes a query on a table, so it needs a handle to both these objects.

AzureMobileQuery – This class makes up the queries. Queries like where, order by and so on.

Ratings – This is the implementation of the ratings table we saw earlier. This class extends the functionality of the Azure table by providing custom operations. Average is an example. All tables might not need an Average operation. For the app, the ratings table returns the average rating for a movie.

Now that we have looked at the classes, let us see how the code works. First the MobileHelper

   1: public class AzureMobileHelper
   2:     {
   3:         string _baseurl;
   4:         string _appKey;
   5:         string _installationId;
   7:         public AzureMobileHelper(string url, string appKey, string installationId)
   8:         {
   9:             _baseurl = url;
  10:             _appKey = appKey;
  11:             _installationId = installationId;
  12:         }
  14:         public AzureMobileTable getTable(string tableName)
  15:         {
  16:             return new AzureMobileTable(tableName);
  17:         }
  19:         public string Execute(AzureMobileQuery query)
  20:         {
  21:             string fullUri = _baseurl + query.Uri;
  22:             HttpWebRequest _azureRequest = WebRequest.Create(fullUri) as HttpWebRequest;
  23:             _azureRequest.Headers.Add("X-ZUMO-APPLICATION", _appKey);
  25:             _azureRequest.Headers.Add("X-ZUMO-INSTALLATION-ID", _installationId);
  26:             using (HttpWebResponse restResponse = _azureRequest.GetResponse() as HttpWebResponse)
  27:             {
  28:                 Encoding enc = System.Text.Encoding.GetEncoding(1252);
  29:                 StreamReader _jsonStream = new StreamReader(restResponse.GetResponseStream(),enc);
  30:                 return _jsonStream.ReadToEnd();
  31:             }
  32:         }
  34:     }

The MobileHelper constructor takes three arguments. The url, the appKey and the installation id. The appKey and the Installation Id are used by Azure Mobile Services to authenticate a request. This is based on a setting in the management portal (You can also choose to authenticate using LIVE Id). You will get the appKey and the url from the management portal. I got the installation id from MobileServices.js (this will be in the request header). At the moment, I don’t know of another way to get it.

The getTable method returns a handle to the AzureMobileTable object. We will take a look at the MobileTable constructor momentarily.

The execute method is the method that does the job. It creates a web request, adds the necessary headers and reads the response returning it as a string. Any response received from Mobile Services is in the JSON format. Pretty simple.

   1: public class AzureMobileTable    
   2: {
   3:     string _tableName = string.Empty;
   4:     private  string tableUrl { 
   5:         get{
   6:             return "tables/" + _tableName;
   7:         }
   8:     }
  10:     public AzureMobileTable(string tableName)
  11:     {
  12:         _tableName = tableName;
  13:     }
  17:     public AzureMobileQuery Where(string whereExpression)
  18:     {
  19:         Expression convertedExpression = Expression.Constant(whereExpression);
  20:         if (convertedExpression is MethodCallExpression)
  21:         {
  22:             return null;
  23:             throw new Exception("Invalid Expression");
  24:         }
  25:         return new AzureMobileQuery(tableUrl + "?$filter=" + whereExpression);
  26:     }
  27: }

The AzureMobileTable class in a way, is the glue that sort of holds everything together. It does this very simply, by building the URIs. The constructor takes in the table name and builds the URI for a table by prefixing  tables/.

At the moment, the class only has one filter operation which is Where. It first validates if this is a valid LINQ Expression and if it is, constructs the appropriate URI. I will be adding more operations, but you get the idea. The last class we will see in this post is the AzureMobileQuery

   1: public class AzureMobileQuery
   2: {
   3:     public string Uri { 
   4:         get{
   5:             return _uri;
   6:         }
   7:     }
   8:     private string _uri;
   9:     public AzureMobileQuery(string uri)
  10:     {
  11:         _uri = uri;
  12:     }
  13: }

The class is pretty much self explanatory. The last piece of the jigsaw is the Broker class that initiates the call.

   1: public string getRatingsbyId(int movieId)
   2:         {
   3:             AzureMobileHelper _helperClass = new AzureMobileHelper("<url>", "<appKey>", "<installationid>");
   4:             AzureMobileTable _moviesCollection = _helperClass.getTable("ratings");
   5:             AzureMobileQuery _query = _moviesCollection.Where("MovieId eq '" + movieId + "'");
   6:             if (_query != null)
   7:             {
   8:                 return _helperClass.Execute(_query);
   9:             }
  10:             return String.Empty;
  11:         }

The method instantiates the helper class with app specific url, app key and installation id. As explained before, it then gets a handle to the table that the query needs to be executed on and the actual query that gets executed. The query in this case just filters all entries for a given movie id.

I have consciously not touched on the ratings class because it solves another problem area that I will deal with in the next post. The above code is just an illustration of how services can call Azure Mobile Services.

The fact that Azure Mobile Services is based on REST gives the developers great flexibility on how to access it and what to do with it. I am not sure when the Mobile Services team plan to release a client library for services or if they even plan to, but if you need to access the services from a service, this has hopefully given you a starting point. Happy Coding!!!

No comments:

Post a Comment