I recently attended a session at CocoaConf DC on Windows Azure Mobile Services for iOS Applications given by Microsoft Technical Evanglist Chris Risner. Azure is a cloud based enviroment similiar to AWS from Amazon that allows you to quickly build and deploy applications and services. I'd like to share what I took away from this session by walking through a demo application.

Microsoft recently introduced Windows Azure Mobile Services for mobile app development. The idea is that developers could use the same services for multiple mobile platforms. Windows Azure Mobile Services currently provide support through the SDK's that are available for Windows Store, Windows Phone 8, iOS, Android, and HTML5 apps. In this blog post I will talk about how to accomplish this task for the iOS platform by creating a simple app to capture temperature readings.

Creating the Azure Service

To get started the first thing you will need to do is go to the Azure Management Portal and register for a new account, or login if you already have an existing account. Currently Microsoft is offering a preview that will allow you to run up to 10 mobile services at a time and will only charge you a monthly data storage fee (around $5 a month for 100 MB worth of data).

After logging in you will see your dashboard. Click on the Mobile Services tab and you will see a screen like the one below. Then click on the link that says "Create A New Mobile Service" or the "New" button in the lower left corner.

You will then be prompted to create your new mobile service. In the URL box enter a name for your service. This will generate a new service with a base URL of yourservicename.azure-mobile.net. You can select an existing database or create a new one. When creating a new one, you will also need to provide a destination region. It is recommended that you use the region that is closest to where you or your users will be because of additional bandwidth costs and higher latencies. In this sample app I have chosen to create a new database instance in the East US region. (One thing to note is that this region can be changed later. You may also add additional servers in different regions to support an expanding customer base. This of course will affect pricing. There is a pricing calculator available to help you estimate how much it will cost to use the various levels of service available. The pricing calculator can be found here.)

Since we are creating a new database instance we will next have to configure it. First, specify the name; in this case it is "TemperatureReadings". Then specify the server; in this app I'm choosing to use a New SQL database server. Lastly supply a user name and password. I'm also choosing the Eastern US region. You don't have to choose the same region as your service, but it is recommended that you do so for the same reasons you would want to choose a region close to you and your users for the service itself. Click the checkmark button to continue.

Azure will now create the new Mobile Service as well as any database servers or other instances that need to be created. After everything is created, Azure offers you links to develop for each of the supported development platforms. Click on iOS and you will see some links on how you would get started with creating a new iOS app or adding Azure Mobile Services to an existing app.

For this example I will connect to an existing iOS app. If you choose to create a new app, Azure will provide you with a pre-built Todo list template, which is good for a beginner but ends up having a lot of code we would need to remove. To hook up an existing app, there are two easy steps: download the iOS SDK and add a reference to this framework in your project.

After creating the new app and adding the SDK, you will need to go back to the Azure management portal under the "Data" tab to create a table to store your data. Click on "Add a table" link to create a new table.

You will then be prompted to complete the new table information. Fill in the new table name, which we will call "Reading". For now leave all the CRUD permissions as "Anybody with the Application Key", but keep in mind the other options are "Everyone", "Only Authenticated Users", and "Only Scripts and Admins". Eventually we will change this to "Only Authenticated Users", but I want to make sure the app will work against the Azure Mobile service with only the basic application key.

Click the checkmark button and we are now ready to start writing some code. Your first thought is probably "Wait a minute; we haven't defined any columns on our table!", but that isn't required. Windows Azure Mobile Services databases are set up with Dynamic Schema enabled, which will auto-generate columns based on the data received. Below is a table with supported types and their SQL equivalent:

JSON Value

T-SQL Type

Numeric values (integer, decimal, floating point)

Float

Boolean

Bit

DateTime

DateTimeOffset(3)

String

Nvarchar(max)

If you don't trust Dynamic Schema, you can always configure the columns through the management portal manually, but for this app we'll let Windows Azure Mobile Services to configure them dynamically.

Building The App

Now that the service is set up and running, we can begin building our app. Fortunately Microsoft has provided a few easy-to-use classes in the SDK to make interacting with the new service a snap. MSClient is the starting point for interacting with Azure Mobile Services. The simplest way to use this class is to use the convenience method clientWithApplicatinURLString:withApplicationKey: to initialize a new instance with the Azure URL and the application Id. The syntax is:

MSClient <span class="sy0">*</span>newClient <span class="sy0">=</span> <span class="br0">[</span>MSClient clientWithApplicationURLString<span class="sy0">:</span><span class="co3">@</span><span class="st0">"https://temperaturereadings.azure-mobile.net/"</span> withApplicationKey<span class="sy0">:</span><span class="co3">@</span><span class="st0">"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"</span><span class="br0">]</span>;

After the client is created the next thing we'll need to do is create an instance of an MSTable that we can use to actually interact with our Reading table. The MSTable class has methods for performing your basic CRUD operations. To create the MSTable, the syntax is:

MSTable <span class="sy0">*</span>readingTable <span class="sy0">=</span> <span class="br0">[</span>newClient getTable<span class="sy0">:</span><span class="co3">@</span><span class="st0">"Reading"</span><span class="br0">]</span>;

We are now ready to begin interacting with the Azure Mobile service. We will need to build a method to retrieve all of the records available in the Reading table. For this app we'll use the readWhere:completion: method. This method will return all the items that match the NSPredicate. The results will be returned in the completion block along with a total count and any errors that might have occurred. To query the Reading table for all records where the temperature readings have been verified you would do this:

<span class="co2">// Create a predicate that finds items where temperatureValidated is true</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span class="kw5">NSPredicate</span></a> <span class="sy0">*</span> predicate <span class="sy0">=</span> <span class="br0">[</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/"><span class="kw5">NSPredicate</span></a> predicateWithFormat<span class="sy0">:</span><span class="co3">@</span><span class="st0">"temperatureValidated == YES"</span><span class="br0">]</span>;
 
<span class="co2">// Query the Reading table and update the readings property with the results from the service</span>
<span class="br0">[</span>self.readingsTable readWhere<span class="sy0">:</span>predicate completion<span class="sy0">:^</span><span class="br0">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span class="kw5">NSArray</span></a> <span class="sy0">*</span>results, NSInteger totalCount, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a> <span class="sy0">*</span>error<span class="br0">)</span> <span class="br0">{</span>
 <span class="kw1">if</span> <span class="br0">(</span>error<span class="br0">)</span><span class="br0">{</span>
 <span class="co2">//Handle error</span>
 <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
 <span class="co2">// process results</span>
 <span class="br0">}</span>
<span class="br0">}</span><span class="br0">]</span>;

Adding an item is also very easy with the insert:completion: method. The insert parameter is an NSDictionary, and when I first saw that it used dictionaries instead of typed classes I was a little disappointed. Typically when I write code I prefer to work with typed classes because it helps prevent typos, which is very easy to do when you are just using string keys in a dictionary. Typed classes also help to prevent the wrong type of data making it into your objects. After I thought about it for awhile this made sense because the Windows Azure Mobile Service is basically a REST API that accepts a JSON object as the body. Converting and NSDictionary to a JSON object is very easy using the NSJSONSerialization class. For this app I created a CTCReading class to represent the data that will be going into the table. I added a toDictionary method to the class to convert the class into an NSDictionary object for inserting and or saving. The keys in the dictionary match the column name in the table and Azure Services will attempt to determine the column type based on the property type of the dictionary value. Below is a sample of how to insert a record:

 
<span class="br0">[</span>self.readingsTable insert<span class="sy0">:</span><span class="br0">[</span>reading toDictionary<span class="br0">]</span> completion<span class="sy0">:^</span><span class="br0">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span class="kw5">NSDictionary</span></a> <span class="sy0">*</span>result, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a> <span class="sy0">*</span>error<span class="br0">)</span><span class="br0">{</span>
 <span class="kw1">if</span> <span class="br0">(</span>error<span class="br0">)</span> <span class="br0">{</span>
 <span class="co2">// Handle error</span>
 <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
 <span class="co2">// Handle success.</span>
 <span class="co2">// result should match the dictionary passed in with an id key for the newly created record.</span>
 <span class="br0">}</span>
<span class="br0">}</span><span class="br0">]</span>;

The update and delete methods work in a very similar fashion to the insert method. As you can see working with the Azure Mobile Service from iOS is very simple to do.

Securing The Application

Now we have a Windows Azure Mobile Service to store all of our data, and an application to read and write to the service, but we have a problem. Anyone that uses this app has unlimited access to all of the data in the service and for this app that is probably okay, however if we were developing a banking application I probably don't want someone else to see all of the data. Fortunately Microsoft has provided a very simple way to secure Azure Mobile Services. The first thing to secure is the permissions on the Reading table. In the Azure management portal, select the table, select the Permissions tab, then change permissions for all CRUD operations to "Only Authenticated Users"

The Azure service will then need to be configured to work with one of the supported identity providers: Microsoft Account, Facebook, Twitter, or Google. During the CocoaConf session he did mention that it was possible to roll your own provider, but he didn't cover that during the session. For simplicity it wiall also not be covered in this post. For this app I have chosen to use Google authentication. First, you need to register your app for Google login with mobile services and receive a Client ID and Client secret. This can be done at the Google APIs console found here.

Once you have this information go back to the management portal and click on the Identity tab. Scroll down to the Google settings section and enter the Client ID and the Client secret from the Google API registration page.

The service will now require the user to authenticate using their Google account in order to perform each of these actions, but we still haven't completely solved our issue of preventing other users from seeing our data. In order to do this we will need to apply some scripts to the tables to ensure that each user only has access to their own data. To do this select the Reading table from the Data tab and click on the Script tab. Then select the Insert operation and change the script so that it looks like this:

function insert<span class="br0">(</span>item, user, request<span class="br0">)</span> <span class="br0">{</span>
 <span class="kw1">if</span> <span class="br0">(</span>typeof item.temperature <span class="sy0">===</span> <span class="st0">'number'</span> <span class="sy0">&</span>amp;<span class="sy0">&</span>amp; item.temperature <span class="sy0">&</span>gt;<span class="sy0">=</span> <span class="sy0">-</span><span class="nu0">20</span> <span class="sy0">&</span>amp;<span class="sy0">&</span>amp; item.temperature <span class="sy0">&</span>lt;<span class="sy0">=</span> <span class="nu0">120</span><span class="br0">)</span><span class="br0">{</span>
 item.userId <span class="sy0">=</span> user.userId;
 request.execute<span class="br0">(</span><span class="br0">)</span>;
 <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
 request.respond<span class="br0">(</span>statusCodes.BAD_REQUEST, 
 <span class="st0">'Temperature must be between -20 and 120 degrees Fahrenheit'</span><span class="br0">)</span>;
 <span class="br0">}</span>
<span class="br0">}</span>

There are a couple of things going on in this script. We are adding the user.userId to our item before inserting, and we are also validating our data to ensure that the temperature passed in is within the range we have defined as "acceptable" (between -20 and 120 degrees).

Now that we have the userId in the table we can restrict select queries to the specific user that is requesting the data. This is also done via script. Select the Read operation and modify the script so that it looks like this:

function read<span class="br0">(</span>query, user, request<span class="br0">)</span> <span class="br0">{</span>
 query.where<span class="br0">(</span><span class="br0">{</span> userId<span class="sy0">:</span> user.userId <span class="br0">}</span><span class="br0">)</span>;
 request.execute<span class="br0">(</span><span class="br0">)</span>;
<span class="br0">}</span>

This applies an additional filter to the read query that is passed in so that the service will only return this user's data. The ability to apply scripts to all of the CRUD operations on the server is a very powerful tool that makes interacting with theses services even easier.

The last thing that we have to do is to actually challenge the user to provide their credentials in the app so that they can access their data. Fortunately Microsoft provides methods on the MSClient to make this an easy task. There is a currentUser property of type MSUser on the MSClient that will be null if the user isn't authenticated. If the user is not authenticated create a new MSLoginController using theloginViewControllerWithProvider:completion method on the MSClient instance. This login controller encapsulates the authentication process with whichever provider you have chosen and will execute the completion block upon completion of authentication, whether successful or not. This code would look something like this:

 
UIViewController <span class="sy0">*</span>controller <span class="sy0">=</span> <span class="br0">[</span><span class="br0">[</span>CTCReadingsService sharedService<span class="br0">]</span>.client
 loginViewControllerWithProvider<span class="sy0">:</span><span class="co3">@</span><span class="st0">"google"</span>
 completion<span class="sy0">:^</span><span class="br0">(</span>MSUser <span class="sy0">*</span>user, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span class="kw5">NSError</span></a> <span class="sy0">*</span>error<span class="br0">)</span><span class="br0">{</span>
 <span class="kw1">if</span> <span class="br0">(</span>error<span class="br0">)</span><span class="br0">{</span>
 <span class="co2">// Handle Error</span>
 <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
 <span class="co2">// Handle Success</span>
 <span class="br0">}</span>
 
 <span class="br0">[</span>self dismissViewControllerAnimated<span class="sy0">:</span><span class="kw2">YES</span> completion<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">]</span>;
 <span class="br0">}</span><span class="br0">]</span>;
 
<span class="br0">[</span>self presentViewController<span class="sy0">:</span>controller animated<span class="sy0">:</span><span class="kw2">YES</span> completion<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">]</span>;

In this post we covered how to create a new Windows Azure Mobile Web Service. We learned how to create a new iOS application and utilize the Azure Mobile Web Service SDK to interact with this service. We have seen how to secure the service and we learned how to authenticate the user in our app. Windows Azure Mobile Web Services provide developers with many more features than those we discussed in this post, things like Push Notifications, paging, console access, and logging. You should now have enough to get your iOS app with Windows Azure Mobile Web Services up and running in no time.

Sample app code can be found here.

UPDATE:

Chris Risner has recently published a blog that covers all the various forms of authentication for Windows Azure Mobile Services, including rolling a custom Auth Provider. The post can be found here.