Windows Azure

Book review: Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 (Geoff Webber-Cross)

During the last months, I used the few times of my spare time when I wasn’t in the mood for programming to read Geoff’s latest book for diving deeper into Azure Mobile Services. Geoff is well known in the community for his Azure experience, and I absolutely recommend to follow him! I am really glad he asked me to review his book and need to apologize that it took so long to get this review up.

The book itself is very well structured with a true working XAML based game that utilizes both Windows 8 and Windows Phone 8 and connects them to one single Mobile Service.

Even if you are completely new to Azure, you will quickly get things done as the whole book is full of step-by-step instructions. Let’s have a quick look on what you will learn while reading this book:

  1. Prepare your Azure account and set up your first Mobile Service
  2. Bring your Mobile Service to life and connect Visual Studio
  3. Securing user’s data
  4. Create your own API endpoints
  5. use Git via the console for remote development
  6. manage Push Notifications for both Windows and Windows Phone apps
  7. use the advantages of the Notification hub
  8. Best practices for app development – some very useful general guilty tips!

I already use a Mobile Service with my Windows Phone App TweeCoMinder. I have already started a Windows 8 version of that app, which basically only needs to be connected to my existing Azure Mobile Service to finish it.

Screenshot (359)

While reading Geoff’s book, I learned how I effectively can achieve this and also improve my code for handling the push notifications on both systems. The book is an absolutely worthy investment if you look into Azure and Mobile Services and has a lot of sample code that can be reused in your own application.

As this is my first book review ever, feel free to leave your feedback in the comments.

You can buy the book right here.

Happy coding, everyone!

Posted by msicc in Archive, 0 comments

Getting productive with WAMS: How to handle erroneous push channels

WAMS

As I wrote already in my former article ‘Getting productive with WAMS- about the mpns object (push data to the user’s Windows Phone)’, I needed to add some more detailed error handling to the mpns object on my Mobile Service.

There are two error codes that appear frequently: 404 (Not Found) and 412 (Precondition Failed).

The 404 error code

happens when the push channel gets invalid. Reasons for that can be uninstall or reinstall of the app, or also a hard reset of the users device. In this case, we are following the recommendation of Microsoft to stop sending push notifications via this channel.

There might be several ways, but I prefer to work with SQL queries.  This is how I delete those channels within error: function(error):

if (error.statusCode === 404)
{
 var sqlDelInvalidChannel = "DELETE from pushChannel WHERE id = " + channel.id;
 mssql.query(sqlDelInvalidChannel, {
 success: function(){
	console.log("deleted invalid push channel with id: " + channel.id);
	},
	error: function(err)
	 {
           console.log("there was a problem deleting push channel with id: " + channel.id + ", " + err)
         }
});

As you can see, this is a very simple approach to get rid of those invalid channels.

The 412 error code

needs some more advanced handling. Microsoft recommends to send the push notification as normal, but the code recommends a delay of 61 minutes to resend. Also, with some research on the web, I found out that often the 412 will turn into a 404 after those 61 minutes (at least I found a lot of developers stating this). This is why I went with a different approach. I am going to wait those 61 minutes, and do not send a push notification to those devices.

For that, I do a simple trick. I am saving the time the error shows up in my push channel table, as well as the  time after those 61 minutes. On top, I use a Boolean to determine if the channel is in the delay phase.

Here is the simple code for that, again within error: function(error):

if (error.statusCode === 412)
{
	var t = new Date();
	var tnow = t.getTime();
	var tnow61 = tnow + 3660000;

	var sqlSave412TimeStamp = "UPDATE pushChannel SET Found412Time=" +  tnow + ", EndOf412Hour=" + tnow61 + ", IsPushDelayed = 'true' WHERE id=" + channel.id;

	mssql.query(sqlSave412TimeStamp);
}

Now if my script runs the next time over this push channel, I need to check if the push channel is within the delay phase. Here’s the code:

if (channel.IsPushDelayed === true)
{
	var t = new Date();
	var tnow = t.getTime();
	var EndofHour = channel.EndOf412Hour;
	var tdelay = EndofHour - tnow;

	if (tdelay > 0)
	{
	 console.log("push delivery on id: " + channel.id + " is delayed for: " + (Math.floor(tdelay/1000/60)) + " minutes");
	}
	else if (tdelay < 0)
	{
	 var sqlDelete412TimeStamp = "UPDATE pushChannel SET Found412Time=0 , EndOf412Hour= 0, IsPushDelayed = 'false' WHERE id=" + channel.id;
	 mssql.query(sqlDelete412TimeStamp);
	}
}

As you can see, I am checking my Boolean that I added before. If it is still true, I am writing a log entry. If the time has passed already, I am resetting those time values to 0 respective the Boolean to false.

The script will now check if the push channel is still a 412 or turned in to a 404, and so everything starts over again.

Other error codes

There might be other error codes as well. I did not see any other than those two in my logs, but for the case there would be another, I simply added this code to report them:

else
{
 console.error("error in Toast Push Channel: " + channel.twitterScreenName, channel.id, error)
}

This way, you can easily handle push channel errors in your Mobile Service.

If you have other error codes in your logs, check this list from Microsoft to determine what you should do: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff941100(v=vs.105).aspx#BKMK_PushNotificationServiceResponseCodes

Note: there might be better ways to handle those errors. If you are using such a way, feel free to leave a comment with your approach.

Otherwise, I hope this post will be helpful for some of you.

Happy coding!

Posted by msicc in Azure, Dev Stories, 0 comments

Getting productive with WAMS: about the mpns object (push data to the user’s Windows Phone)

WAMS

When it comes to Mobile Services, there are a lot of things you can do with the user’s data. One of them is to update the Live Tiles of their apps as well as send them Toast Notifications. To understand how the mpns (Microsoft Push Notification Service) is working, please see the image below and read this article on MSDN: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff402558(v=vs.105).aspx

mpns graph

Windows Azure has a pretty basic example to get the Live Tiles updated: http://www.windowsazure.com/en-us/develop/mobile/tutorials/push-notifications-to-users-wp8/. However, this example sends the data from the app to Azure and directly back to the user’s device. It is a good start if you want to understand how it works, but it does not reflect the most common scenario: the server is fetching data with the app closed on the users device.

The most important part: getting a valid push channel from the Push Client Service

Now that we know how the push notification service works, we need our Windows Phone app to acquire a valid push channel. This is done by a few lines of code in App.xaml.cs. First, we need a globally declared push channel:

public static HttpNotificationChannel pushTileChannel { get; set; }

With this global variable we are now able to get a valid push channel into our app and to our Mobile Service:

public static void AcquirePushChannel()
        {
                  pushTileChannel = HttpNotificationChannel.Find("msicc-test");

                if (pushTileChannel == null)
                {
                    pushTileChannel = new HttpNotificationChannel("msicc-test");

                    pushTileChannel.Open();

       //this binds the push notification to your live tile       
       pushTileChannel.BindToShellTile();

       //this binds the push notification to toasts
       pushTileChannel.BindToShellToast();

 }        

                IMobileServiceTable<pushChannel> pushChannelTable = App.MobileService.GetTable<pushChannel>();
                var channel = new pushChannel { Uri = pushTileChannel.ChannelUri.ToString() };
                pushChannelTable.InsertAsync(channel);
           }

The Find(“desiredNameOfChannel”) method creates or finds a channel exclusive to your app and should be the same for all of your users. The Open() method finally opens the connection from your app to the Push Client Service. To automatically receive the updates for Tiles and Toast, we use the BindToShellTile() and BindToShellToast() methods.

Important for images:

You need to allow the url(s) the images can be from. To this, you need to add the desired uri in the BindToShellTile() method. If you have more than one uri the images come from, just create a Collection of Uri and add them to the BindToShellTile() method  overload. Please note that only the top level domain needs to be allowed (specifying folders is not supported).

public static Collection<Uri> allowedDomains = 
            new Collection<Uri> { 
                                                new Uri("https://yourmobileservice.azure-mobile.net"), 
                                                new Uri("https://yourseconduri.com/") 
                                              };

pushTileChannel.BindToShellTile(allowedDomains);

But that’s not all. We need to add the push channel uri  also to our Windows Azure table to update the users data. This what the last three lines of codes are for. I highly recommend to separate the push channel table from your user data table, to be able to operate easily on this table. In order to avoid duplicate channels (which can be very annoying for users and yourself), we should update our server side data script:

function insert(item, user, request) {

   var channelTable = tables.getTable('pushChannel');
        channelTable
            .where({ uri: item.uri })
            .read({ success: insertChannelIfNotFound });
        function insertChannelIfNotFound(existingChannels) {
            if (existingChannels.length > 0) {
                request.respond(200, existingChannels[0]);
            } else {
                request.execute();
            }
        }
}

This way, you are all set up for updating your app’s Live Tile and for Toast Notifications. But until now, our Mobile Service does not send any data to our app.

How to update Live Tiles and send Toast Notifications from Mobile Services

Once our server side code has fetched all data, we certainly need to update our user’s Live Tiles or even send Toast Notifications. We are able to send the following types of Tiles and Notifications:

The FlipTile is the coolest of all and has the most options you can use. That’s why I choose it over the ‘normal’ Tile. To get the data out to our users, we are using this code:

//call the push channel table

var channelTable = tables.getTable('pushChannel');

//send toast and Tile:

channelTable
    .where({user:userid})
    .read({
        success: function(channels){
            channels.forEach(function(channel) 
                {
                    push.mpns.sendToast(channel.uri, {
                        text1: ToastText1,
                        text2: ToastText2
                        }, {
                    success:function(pushResponse) {
                        console.log("Sent toast: ", channel.id, pushResponse);
                    },
                    error: function (error){
                        console.error("error in Toast Push Channel: " +  channel.id, error)
                    }
                });
                push.mpns.sendFlipTile(channel.uri, {
                     backgroundImage: backgroundImage,
                     backTitle: backTitle,
                     backContent: BackContent,
                     smallBackgroundImage: SmallBackgroundImage,
                     wideBackgroundImage: WideBackgroundImage,
                     wideBackContent:  WideBackContent,

                }, {
                    success:function(pushResponse) {
                        console.log("Sent tile:" ,  channel.id, pushResponse);
                    },
                    error: function (error){
                        console.error("error in Push Channel: "  channel.id, error)
                    }
                });
            });
        }
    });

Like you can  see, we are using quite a few fields in the mpns object payload. You can click on the types above to see which fields are supported on each type.

Images that you send to your users are sent need to be a valid url to the image. The maximum size is 80 KB. If your Images are bigger, they will not be sent!

The mpns object has both a ‘success’ and an ‘error’ callback. The error callback is automatically written to the log. However, it is very hard to identify which id is causing the error in this case. That’s why you should implement it in the way I did above. This way, you know exactly which id is causing an error and which id received their update correctly.

We are also able to add some extra functions to respond to the success and error callbacks. I still need to do this on my WAMS, and I will write about the measures I took in the different cases once I did it (I only started using Azure a few month ago, so I am also still learning). If you are interested, here is a list with all possible response codes for the mpns object: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff941100(v=vs.105).aspx#BKMK_PushNotificationServiceResponseCodes

Conclusion

Like you see, Windows Azure Mobile Services allows us to send out updates to the user very easy within less than an our for setting it up. There are a few things we need to take into account – in fact, most of this points took me a lot of time to find out (as it is the first time I use push in general). As always, I hope this post is helpful for some of you.

Until the next post, happy coding!

Posted by msicc in Archive, 0 comments

Getting productive with WAMS: how to set up a timeout before running code in an interval

WAMS

I truly love Windows Azure Mobile Services, as it provides an easy way to connect Windows Phone apps to the cloud and also manages Live Tiles and Toast Notifications via Push. This way, we don’t have an impact on the users battery life by running background agents.

However, scheduled scripts are only able to run in predefined time windows, with 15 minutes at lowest.

It may happen that you want to run your script in shorter intervals, as I am currently implementing into mine.

The functions:  setTimeout() and setInterval()

The difference between those two is pretty simple:

  • setTimeout() is running the function included only once after the time in milliseconds has passed
  • setInterval() is running the function included in an interval set up in milliseconds until it gets stopped

Knowing this, it is pretty simple to set up those two functions each for itself:

setTimeout(function() { 
//code to run 
}, time in milliseconds);

setInterval(function() {
//code to run
}, time in milliseconds);

I highly recommend to declare an interval as a variable. If you won’t do that, the interval will run forever as you never can stop it!

But what if we need first a timeout and then an interval?

That is the problem I was trying to solve over the last two days. I was playing around with all kinds of code constellations to achieve this goal. And I found a solution.

We need to set up a few things to achieve that goal:

  • global variables for the number of runs and the interval
  • a function that only proves if the interval is still valid to run or needs to be stopped
  • our function that should be run in an interval

In my example, I want the code to be executed five times, then the interval should be stopped (cleared). I achieve this goal with a pretty simple if/else clause, like you can see:

if (NumberOfRuns < 6)
{
        console.log("interval ran " + NumberOfRuns + " times");
        doSomething();
        }
        else
        {
        //stoping the interval       
        clearInterval(Interval);
        console.log("interval stopped!");
}

As this is a sample script, I use the function doSomething() to be executed. This represents your code that should be executed if the interval is still valid. Only important thing: counting up the number of runs every time the function is hit.

    //counting up the number of runs with every call of the function
    NumberOfRuns++;

    //your code runs here

And in our starting point (the function that has the same name like your script), we finally declare the the timeout as well as we start to count:

   //setting the NumberofRuns to 1 as after timeout the first run starts
   NumberOfRuns = 1;
   console.log("start")

   //settings timeout to call the function that proves if the interval is still valid
   setTimeout(function(){
       //interval has to be defined in this scope, otherwise it will not be accepted
       //we also need a variable for the interval to be able to stop the interval
       Interval = setInterval(RunInterval, 5000);
       console.log("timeout is over");
   },15000);

First, we start our counter with 1, as after the timeout the code will be executed for the first time. I added also some logging functions, so you can prove everything is running fine.

The content of the global variable “Interval” has to be declared within the timeout, otherwise we will not be able to set the interval for our function.

Once you figured all the points above, it is pretty easy to implement this into your running script.

If you want to play around with this and see what the log looks like, here is the full WAMS scheduler script:

//declaring global variables
var NumberOfRuns;
var Interval;

//function to execute in interval
function doSomething()
{
    //counting up the number of runs with every call of the function
    NumberOfRuns++;

    //your code runs here
}

//this function proves if the the interval is still valid
function RunInterval()
{
     if (NumberOfRuns < 6)
        {
        console.log("interval ran " + NumberOfRuns + " times");
        doSomething();
        }
        else
        {
        //stoping the interval       
        clearInterval(Interval);
        console.log("interval stopped!");
        }
}

//main script function (start)
function TestIntervalScript() 
{
   //setting the NumberofRuns to 1 as after timeout the first run starts
   NumberOfRuns = 1;
   console.log("start")

   //settings timeout to call the function that proves if the interval is still valid
   setTimeout(function(){
       //interval has to be defined in this scope, otherwise it will not be accepted
       //we also need a variable for the interval to be able to stop the interval
       Interval = setInterval(RunInterval, 5000);
       console.log("timeout is over");
   },15000);
}

And here is a screen shot from the desired log file:

Screenshot (192)

As I am still pretty new to JavaScript,  there might be also other ways to achieve this. Feel free to leave a comment if you have anything to add/improve on this code.

And as always, I hope this is helpful for some of you when playing around with Windows Azure Mobile Services.

Happy coding!

Posted by msicc in Azure, Dev Stories, 0 comments

Getting productive with WAMS: how to update data for a specific row in a table

WAMS.png

Like I promised, I will share some of the Azure goodness I learned during creating my last app.

This post is all about how to update a specific table entry (like a user’s data) in a Azure SQL table from an Windows Phone app.

First, we need to make sure that there is some data from the user we want to update. I used the LookupAsync () method to achieve that.

IMobileServiceTable<userItems> TableToUpdate = App.MobileService.GetTable<userItems>();
IMobileServiceTableQuery<userItems> query = TableToUpdate.Where(useritem => useritem.TwitterId == App.TwitterId);

var useritemFromAzure = await query.ToListAsync();
var useritemLookUp = await TableToUpdate.LookupAsync(useritemFromAzure.FirstOrDefault<userItems>().Id);

If we want a specific entry, we need a search criteria to find our user and fetch the id of the user’s table entry. In my case, I used the Twitter Id for the query as every user has this on my project.

Now that we have the table row id, we can easily update the data of this specific row with the UpdateAsync() method.

We need to declare which columns should be updated and asign the values to it first. After that, we simply call the UpdateAsync() method.

useritemLookUp.TwitterId = App.TwitterId;
useritemLookUp.LastCheckedAt = DateTime.Now;
useritemLookUp.OSVersion = "WP8";
useritemLookUp.AppVersion = App.VersionNumber;

await TableToUpdate.UpdateAsync(useritemLookUp);

Please note that you need a items class/model to create the update data (which you should have already before thinking about updating the data).

You should wrap this code in a try{}/catch{} block to be able to react to the Exceptions that possibly can be thrown and display a matching message to the user.

That’s already all about updating a specific row in a WAMS SQL table.

As always I hope this post is helpful for some of you.

Happy coding!

Posted by msicc in Azure, Dev Stories, 1 comment

New Series: Getting productive with Windows Azure Mobile Services (WAMS)

WAMS

Now that my current app project is near to go live, I will start a new series about how to get productive with Windows Azure Mobile Services (WAMS).

I will cover some interesting topics in this series, which are not really documented in the very well written “Getting started” series from the Azure team itself.

These topics are (list is subject to be updated if needed):

First, if you want to get  started, you should check out this link: http://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started-wp8/

The tutorial makes you very easy and fast using WAMS.

What can you expect from this series? As always, I will add some of my personal experiences during my journey of creating my app. There were a lot of small stones in my way, and I will also tell you how to remove them. And of course I hope that my posts will help some of you to get their own WAMS story started.

Happy coding everyone!

Posted by msicc in Azure, Dev Stories, 0 comments

How to format Date and Time on Windows Azure

time_Azure

Phew, my first post about my journey on starting development on Windows Azure. I started a few weeks ago using the Mobile Services from Windows Azure, and I did learn a lot about it.

This post is about formatting Date and Time strings, because Azure uses a different format than my Windows Phone app.

If we upload a DateTime String to Windows Azure from a Windows Phone app, it looks like this: 2013-05-04T06:45:12.042+00:00

If we translate this, you have “YYYY-MM-DD” for the date. The letter “T” declares that the time string  is starting now, formatted “HH:MM:ss.msmsms”. The part “+00:00” is the timezone offset.

So far, probably nothing new for you.

Now let’s get to Azure. Azure by standard uses the GMT time for Date strings (DateTime() in JavaScript = Date()). I have written a scheduler which fetches data from another web service and puts it into my table. Naturally, I wanted to know when the data were last checked, so I added a column for it.

Then I did what everyone that is new to JavaScript has done and added a variable with a new Date(). And now the trouble begins. The output of new Date() is a totally different string: Sat, 04 May 2013 07:02:51 GMT.

Sure, we can parse and convert it within our app, but that would need (although not much) additional resources. So I decided to let to Azure the conversion to a Windows Phone readable string.

How do we  manipulate the Date()-string?

I binged a bit and finally found a very helpful page, that explains all about the JavaScript Date() object: http://www.elated.com/articles/working-with-dates/

I then started off with the following code:

var d = new Date();
var formattedDate = d.getFullYear() + "-" + d.getMonth() + "-" + d.getDate();
var formattedTime  = d.getHours() + ':' d.getMinutes() + ':' + d.getSeconds();
var checkedDateTime = formattedDate + "T" + t;

Those of you that are familiar with JavaScript will immediately see what I did wrong. Let me explain for the newbies:

First thing, date().getMonth is zerobased. So we will always get a result that is one month behind. We have to get it this way for the correct month:

d.getMonth()+1

But that is not all. If you will use the code above, your result will look like this: 2013-5-4T7:2:51

JavaScript does not use leading zeros. If you want to insert it into a date formatted column, you will get the following error from Azure:

Error occurred executing query: Error: [Microsoft][SQL Server Native Client 10.0][SQL Server]Conversion failed when converting date and/or time from character string.

So we need to add the leading zero before inserting it. Luckily we are able to that very easy. Here is my implementation:

var d = new Date();
var formattedDate = d.getFullYear() + "-" + ('0' + (d.getMonth()+1)).slice(-2) + "-" + ('0' + d.getDate()).slice(-2);
var formattedTime  = ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2) + ':' + ('0' + d.getSeconds()).slice(-2);
var checkedDateTime = formattedDate + "T" + t;

What have we done here?

We are adding the leading 0 to each object string. The slice(-2) is for only picking the last two numbers. To make it more clear: if we have 9 as hour, adding the zero in front results in 09. Picking only the last two numbers by .slice(-2) results in still in 09. If we have 10 as hour, adding the leading zero results in 010. But the .slice(-2) operation will cut it back to 10. Easy enough, right?

If we run the code above to get the Date and Time, the result will look like this: 2013-05-04T7:02:51

The timezone offset is automatically added to the date when we update the table. If we now send the data to our Windows Phone or Windows 8 app, no conversion is needed as we already have a correctly formatted string.

I hope this is helpful for some of you and will save you some time.

Happy coding everyone!

Posted by msicc in Azure, Dev Stories, 0 comments