Editor’s note: The following post was written by Microsoft Integration MVP Scott Seely
This article assumes that you have:
· A Windows Azure subscription.
· Experience with C#/XAML (this lets me stick with one language/markup style in the article for the phone and tablet).
· Visual Studio 2012.
You can get the code for this project from github: https://github.com/sseely/wams-demo.git
I’ve been building software since the early 1990s. Because of my own personal interests, I frequently get involved in the architecture of components that handle security, consistent data storage, and server/client interactions. This expertise means that even my personal projects tend to be a bit ambitious in terms of security, distribution, and capability. When building something, I typically prototype an idea first, see how it works locally, and then iteratively work in the back end. Anyone who builds an application does this and has the same, basic needs. I was very excited when I learned that Microsoft launched something to meet those needs called Windows Azure Mobile Services (WAMS). WAMS is a very nice, general purpose back end that handles the needs of many applications. Today, it supports applications running on a diverse range of devices from Windows 8, Windows Phone 8, and Apple iOS. Support for Android is “coming soon.”
In this post, we’ll take a look at what WAMS provides to authenticate a user, store data, and push out notifications to connected devices from other parties. What most tablet and smartphone applications need is the ability to do the following:
1. Secure the application data such that only the data owner and, possibly others, can see it.
2. Have some backend bits that run alright on Windows 8 and other mobile platforms.
3. Make sure that updates from one device get pushed to everyone else who might be interested in the data.
In the rest of this post, we will walkthrough how WAMS supports these scenarios.
Getting Started
To use WAMS, go over to https://manage.windowsazure.com/and create a new Mobile Service. WAMS is currently in beta and you may have to sign up for the beta before Mobile Services lights up in the management portal. Once you have Mobile Services enabled, you simply click on Mobile Services, then New,thenMobile Service, then Create. Pick a URL for your service and a region to run in. I chose jeanius-shoppinglist, in the Western US Region with a new SQL Database. You also get to make a few more decisions about how big the database should be. Feel free to use a Web Database with a size of 1 GB if you are following along. When the Mobile Service is completed, make sure to download and install the Mobile Services client libraries. You can find links to the libraries on the home page for your Mobile Services app. Just pick a platform. Under Get Started for each platform, you can pick “Create a new … app”.Under Get the tools are links to the SDK for the platform you have chosen.
Thinking about eventually setting up a shopping list, I then created a set of projects:
· For the phone: JeaniusFactory.ShoppingList.Phone (Windows Phone 8 project, Databound App)
· For the Windows 8 devices: JeaniusFactory.ShoppingList.Tablet (Windows Store project, Blank App)
· For the shared data types: JeaniusFactory.ShoppingList.Model (Portable Class Library, for .NET 4.5, Windows Phone 8 and .NET for Windows Store apps)
On the phone and Windows Store apps, I also added a reference to the Windows Azure Mobile Services Managed Client. Then, for each of the App objects in the Phone and Table projects, I added the following code to allow me to talk to WAMS:
private static MobileServiceClient _mobileServiceClient;
public static MobileServiceClient MobileServiceClient
{
get
{
if (_mobileServiceClient == null)
{
_mobileServiceClient = new MobileServiceClient(
"https://jeanius-shoppinglist.azure-mobile.net/",
"[key]");
}
return _mobileServiceClient;
}
}
So far, nothing spectacular and it all built. The next thing I wanted was a way to authenticate users.
Adding Security
In security, we find that many applications conflate authentication with authorization. Many websites require that you login with a username/password specific to that site in order to access that particular site. This is at odds with what we see in the real world. In the real world, I carry around a driver’s license and, occasionally, a passport. These documents are issued by a government that people trust to have verified things like my birthdate, name, and address. I present these documents to get access to loans, through security at airports, and to be served alcohol at a restaurant. On the Internet, we have a number of other common sites that many people use. As an application developer, I can choose to trust these other sites to verify a username/password. Upon verification, these sites can hand my application the equivalent of a passport—a digital token filled with data about the user. In the same way a waiter uses my driver’s license to verify that I can order a beer, I can use the digital token and its data to authorize the user within my application.
In recognition of the fact that most users have an account with Microsoft, Facebook, Twitter, or Google, WAMS provides a mechanism to use any of these four as authentication mechanisms. Since I’m targeting Windows Store and Windows Phone 8 apps, most of the time a user will have a Microsoft ID. I did this in a few steps:
1. Created an application in the Windows Store Portal.
2. Go over to the Live Connect Developer Center to retrieve the key and secret for my application. To do that, just click on the app that was created in the Windows Store Portal, then look for the API Settings group which contains the Client ID and Client secret.
3. Edit the application API settings, configuring the Redirect Domain to point to you mobile application. For my sample app, this is https://jeanius-shoppinglist.azure-mobile.net/. Then, click Save.
4. Copy the Client ID and Secret from #2 into the Microsoft account settings area on the WAMS identity tab.
5. Click Save.
At this point, I just had to add authentication to the applications. Again, this is a small set of steps. For both the Phone and Tablet applications, I opened up MainPage.xaml.cs and added a class variable to track the current user:
MobileServiceUser User { get; set; }
I then added an Authenticate method to get the credentials for the current user to both apps:
private async System.Threading.Tasks.Task Authenticate()
{
if (App.MobileServiceClient.LoginInProgress)
{
return;
}
while (User == null)
{
string message = null;
try
{
User = await App.MobileServiceClient
.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
}
catch (InvalidOperationException)
{
message = "You must log in. Login Required";
}
if (!string.IsNullOrEmpty(message))
{
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}
}
Windows Phone 8 does have a slight change to the above code; change the block that displays the message from 3 lines to this:
MessageBox.Show(message);
Finally, in the MainPage.OnNavigatedTo method for both apps, change OnNavigatedTo to be async and add the following line at the end of the method:
await Authenticate();
If you did everything right, the application will now ask you to login using your Microsoft ID whenever you start the application. We now have authentication working! Next, let’s add the ability to manage a single list.
Managing Data
The application data is actually pretty simple. Pretty much every application that uses these features will start out with a few basic objects, then add objects that are specific to their application. At a minimum, you have Users and UserDevices. This requires two tables which I named User and UserDevice.
For each of the tables, set the permissions to only allow authenticated users to insert, update, delete, or read. Once created, the tables will have an id column that is essentially a C# long named id. You can put the simple objects into a portable class library project so that the binaries can be used in both the Phone and Tablet projects. The downloadable project is a skeleton application that contains everything needed to bootstrap an application that shares its device URI with a central service.
One thing I found really interesting in all of this is that the underlying tables do not require the columns to exist in the database before the columns are used. You can go ahead and manage columns if you like, but you do not have to. A missing column just gets added automatically for you. Data types for the columns are picked out from the JavaScript value that would be used for the column.
When accessing the objects client side, you can use regular old LINQ expressions to select data from the tables. The client libraries take those LINQ expressions and translate them into an OData query. Once received, the messages are then dispatched to the Read operation at the server. For example, I could look up the current user record in the backing store using code like this:
var userTable = App.MobileServiceClient.GetTable<User>();
var currentUser = (await (from aUser in userTable
where aUser.UserId == User.UserId
select aUser).ToEnumerableAsync()).FirstOrDefault();
currentUser would contain the user that matches the query. I could also chose to limit things such that the current user can only ever retrieve their own record. To do this I hook into the scripts that run server side. Each table has accompanying scripts that are executed whenever someone tries to Insert, Update, Delete, or Read a record. The script is not a stored procedure. Instead, the server runs JavaScript within a node.js application running on top of a Windows Azure Web Site. (That’s just an implementation detail that you don’t really need to worry about.)
Let’s look at the Read operation for the User table. By default, it has this implementation:
function read(query, user, request) {
request.execute();
}
If we want to restrict the request to only include the authenticated user, we would add one line to the method, immediately before request.execute():
query.where({UserId: user.userId});
What happens here is any queries to get data from the User table automatically see that the results should be filtered include a UserId that matches the authenticated user. The authenticated user is always delivered in the user parameter. If the table Read doesn’t require an authenticated user, this value may occasionally be null.
Push Notifications
To be able to send push updates, you need to register your application in the application store and go through the basic registration. Details on setting up an account in the Windows Store are detailed here. To do that, you first need to go your WAMS application in the portal and select the Push tab. From here, enter the client secret and package SID on the tab and click on Save.
One thing we might want to do is notify the user when they have logged on at another location. For this, it might be interesting to at least indicate the type of device being used in the notice. We can tell the difference based off the of notification service URL. For example, Windows Phone uses http://sn1.notify.live.netand Windows 8 uses https://bn1.notify.windows.com. This functionality is supported by the global push object. The object has two properties hanging off of it for the Windows Phone and Windows Store named mpnsand wns respectively. Given a device URI, you can push a message to that device with just a short amount of code and a few handlers: one for success and one for errors. When an error happens, the general recommendation is to forget the failed device URL. Typically, that means remove the URL from your data store. For example, to send code via the Microsoft Push Notification Service with a known device URI and message, one would write the following:
push.mpns.sendToast(uri, {text1: "Push", text2: message},
{success: successMns(id),
error: errorMns(id, uri),
});
The success and error functions are then just this:
function successMns(deviceId){
return function (err, results){
if (err.shouldDeleteChannel){
userDeviceTable.del(deviceId);
}
}
}
function errorMns(deviceId, uri){
return function (err, results){
if (err.shouldDeleteChannel){
userDeviceTable.del(deviceId);
}
}
}
For the Windows Notification Service and regular Windows apps, the code is similarly simple. Push out the toast using:
push.wns.sendToastText04(uri, {text1: message},
{success: successWns,
error: errorWns(id, uri)});
Then, handle success and failure with a pair of functions:
function successWns(pushResponse) {
// Do nothing
}
function errorWns(deviceId, uri){
return function(err, result){
if (err.headers['x-wns-notificationstatus'] === "dropped"){
userDeviceTable.del(deviceId);
}
};
}
And, with that, your application is sending out toast to all interested parties!
Summary
WAMS provides a set of functionality to make it significantly easier to go from idea to implementation with your Windows Store and smart phone applications. It implements a lot of the back end services you need, letting you focus on the differentiators: what the application does, business logic, and availability across form factors. The service is currently in beta. Now is a great time to learn what the service does and to engage with the product team at Microsoft.
About the author
Scott Seely is the president of The Jeanius Factory, Inc.. He is a Microsoft Regional Director, Pluralsight author, and Microsoft MVP. He blogs at http://scottseely.com. He is an active member of the .NET community in the Chicago area, helping found That Conference, organize Code Camps, and speaking at user groups throughout the region. Scott has authored and co-authored five books and dozens of articles on software development. When away from his computer, Scott enjoys cooking, a round of golf, a good beer, and hanging out with his three children and his wonderful wife. Follow Scott on Twitter.
About MVP Mondays
The MVP Monday Series is created by Melissa Travers. In this series we work to provide readers with a guest post from an MVP every Monday. Melissa is a Community Program Manager, formerly known as MVP Lead, for Messaging and Collaboration (Exchange, Lync, Office 365 and SharePoint) and Microsoft Dynamics in the US. She began her career at Microsoft as an Exchange Support Engineer and has been working with the technical community in some capacity for almost a decade. In her spare time she enjoys going to the gym, shopping for handbags, watching period and fantasy dramas, and spending time with her children and miniature Dachshund. Melissa lives in North Carolina and works out of the Microsoft Charlotte office.