In my previous posts I have talked about how what Azure Mobile Services really does is provide endpoints for applications to work with. The endpoints are represented as tables which feature four hook points: Insert, Read, Update, and Delete. The HTTP method used for access will dictate which method gets called. Here is the mapping:
- Insert -> HTTP POST
- Read -> HTTP GET
- Update -> HTTP PATCH
- Delete -> HTTP DELETE
While this is a very simple API it still requires an understanding of how to make network requests from within each platform and configuring those requests with the appropriate parameters. While not overly difficulty it is very monotonous and tedious and isn’t something we should concern ourselves with. This is where the Client Libraries for Azure Mobile Services come into play (http://www.windowsazure.com/en-us/develop/mobile/developer-tools/). The library allows for these operations to be abstracted behind a common access paradigm allowing you to write similar code on the platforms. I want to talk about how the iOS and Android versions work.
Working with iOS
I should point out that much of what you will see here is relevant to the Android side of things as well. To begin, you must follow the appropriate instructions for referencing Azure Mobile Services Framework into Xcode; the instructions lay it out quite nicely. Its really nothing more than dragging the output folder from the zip and dropping it on your Xcode project. Pretty simple as far as Xcode project referencing goes.
– (void)loadChannels: (NSString *) token {
MSClient *client = [MSClientclientWithApplicationURLString:@”YOUR MOBILE SERVICE URL”
withApplicationKey:@”YOUR APPLICATION KEY”];
NSString *customTableName = [NSString stringWithFormat:@”channels?token=%@”, token];
MSTable *channelsTable = [client getTable:customTableName];
[channelsTable readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error) {
NSMutableArray *channelArray = [[NSMutableArray alloc] initWithCapacity:totalCount];
for (int i=0; i<items.count; i++) {
NSDictionary *itemValue = ((NSDictionary *)[items objectAtIndex:i]);
int channelId = [[NSString stringWithFormat:@”%@”, [itemValue objectForKey:@”Id”]] intValue];
NSString *channelName = [NSString stringWithFormat:@”%@”, [itemValue objectForKey:@”Name”]];
int associationId = [[NSString stringWithFormat:@”%@”, [itemValue objectForKey:@”AssocId”]] intValue];
BOOL isRegistered = [[NSString stringWithFormat:@”%@”, [itemValue objectForKey:@”Registered”]] boolValue];
Channel *channel = [[Channel alloc] initWithChannelId:channelId
Name:channelName
Registered:isRegistered
AssociationId:associationId];
[channelArray addObject:channel];
}
[delegate channelsLoadComplete:channelArray];
}];
}
So what is happening here is a Read operation. Notice that when I specify the name of the table I am using the endpoint name (‘channels’) and passing a token value. The readWithCompletion method executes a read with an empty query (you can specify OData queries to your endpoints). I also define a block of code which will get executed when the method returns. As you can see, we are doing a read operation; under the covers the client is using GET to make the request.
This pattern is used throughout the iOS version of the Mobile Services client, for all other operations. For example:
– (void)registerChannel:(NSInteger) channelId withToken:(NSString *)token {
MSClient *client = [MSClientclientWithApplicationURLString:@”YOUR MOBILE SERVICE URL“
withApplicationKey:@”YOUR APPLICATION KEY“];
MSTable *clientChannels = [client getTable:@”ClientChannels”];
NSMutableDictionary *channelDictionary = [[NSMutableDictionaryalloc] init];
[channelDictionary setObject:@”0″ forKey:@”ClientType”];
[channelDictionary setObject:token forKey:@”Token”];
[channelDictionary setObject:[NSString stringWithFormat:@”%d”, channelId] forKey:@”ChannelId”];
[clientChannels insert:channelDictionary completion:^(NSDictionary *item, NSError *error) {
NSInteger assocId = [[NSStringstringWithFormat:@”%@”, [item objectForKey:@”AssocId”]] integerValue];
[delegate registrationComplete: assocId];
}];
}
Similar pattern in use here, although unlike the other libraries (Android, Windows 8, and Windows Phone) we specify a hash table as our JSON object rather than some sort of class based representation. The effect is the same. You see the completion block definition for what ail happen when the request completes. This block is executed whether or not there is an error, so in a real application checks should be done and the appropriate response raised. Under the hood, the PATCH HTTP method is used. The reason for this, per Josh Twist from Microsoft, is an entire object need not be passed for the update to occur. This means, in a table with three fields the object could contain only 1 value + the id. Only that one value would be updated, hence “patching”.
Documentation: none
Android
As I said earlier, the Mobile Services API is intentionally consistent in how it is interacted with across the supported platforms. That said, each platforms has its own way of dealing with blocking code, that is code which would normally block the UI thread making an application appear unresponsive. Like iOS, Android employs blocks of code as callbacks. Here is an example of the same read operation from above using the Mobile Services client in Android:
Apologies, I can’t seem to figure out how to paste colored source code from IntelliJ into Mars Edit, so you call get a picture. The chief differences here are we see that the Mobile Services client allow us to specify a block of code for execution upon completion. Here we are using the GSON library’s JsonElement class to get the values from the array of JSON objects being returned from the server. I should point out that I pass a reference to the MainActivity to this code, however, so as to ensure that only the method I used are exposed, I use an interface.
Lets look at Insert:
Similar to the iOS example, its almost the exact same code. It takes advantage of Java as an OO language and the supported “blocks” concept for long running methods.
Documentation: http://dl.windowsazure.com/androiddocs/
Closing
Consistency is the hallmark of code clean code. Things that are written similarly are easier to debug because we can more easily follow code when we have an idea of how it works. Being able to infer from other parts of the application is an essential skill in programming, consistency amplifies are ability to do that. While you could easily implement the appropriate calls using things like NSURL in iOS or HttpClient in Java, this would cause code to be different and lead to possible complications when making changes. Using the mobile services client library, these platforms specific details are not only handled for you, but are done so in a way that doesn’t impact the way you would normally write code for a system.
Up next: the Windows 8 and Windows Phone client libs