Building for Cost Part 2

In the last post, we looked at ways to separate content using different pieces of Windows Azure for the benefit of creating a more cost-effective solution using Windows Azure Web Sites (WAWS) and Windows Azure Storage for storing images and other binary/static files.   Although we’re looking at this just for cost efficacy, frankly that approach just makes sense from an availability and performance aspect, too. Another fantastic service is Windows Azure Mobile Services (WAMS), but unsurprisingly, it has its own cost structure outlined here: Similar to WAWS, you can have up to 10 services for free.  But, the way these services are metered are completely different, and it might change the way we build an application. First, let’s discuss the free tier.  The current metering, limited to 100 devices, means that using an authenticated client (that is, any client using the SDK) renders this tier useless for anything other than testing.  For example, here’s my low-use application: We’re not really incurring many API calls, but our device count is pretty high.  When I designed the app, these meters weren’t in place, but if they were I’d design the app differently.  Hopefully, we’ll see some changes in this as the current plan is a bit inflexible.  What this means, though, is that for my app to keep working, I need to upgrade to the $25/mo plan.  By making a few specific decisions early on, we can build the application to take advantage of both WAMS and WAWS.  For example, in WAMS, custom API calls can be made and invoked over HTTP.  I leveraged this in Brew Finder for several items: brewerydb’s callback, live tiles, and web services that don’t require authentication.  Because these calls are made from “non-devices,” the usage looks like so: I’m not exactly sure why this is showing zero bytes out (it could be for the time duration shown in this graph, it’s not significant enough), but the 0 devices and API calls count is accurate.  We also have the option to deploy another WAWS with node.js, if we’d like to stick with server-side javascript.  Remember, the database that is used can certainly be shared by any number of WAWS, WAMS, etc.  So, if you need to curb back on your API calls, offload that work to a WAWS instead where the calls are not metered if you don’t need WAMS specific features (like authentication).  Summary The biggest challenge in developing a cloud backed app is guesstimating the usage.  The first step, though, is to understand what is being measured – API calls, devices, bandwidth, CPU time, etc.   Keeping the application architecture spread across multiple services for different functions (authentication, live tiles, etc.) is a great way to make the application flexible so you can take advantage of the way each service is metered, bearing in mind this is always subject to change. Having trouble estimating or getting started?  Drop me a note or leave a comment on this post.  I’d be happy to help you work through some ideas. 

Creating a Great Mashup Part 3

This post details features used by Earthquake Explorer, a Windows 8 app that displays earthquake information on Bing maps.   Earthquake Explorer was based off of the Earthquakes mashup starter kit on github.  Read part 1 here.  Read part 2 here.  We left off Part 2 talking about creating a compelling live tile in Windows 8.   This really is a must-do feature in Windows 8 – primarily because a live tile creates a more compelling app experience.  It encourages the user to keep the live tile ‘pinned-left’ (that is, more likely on their primary screen), and encourages the user to open the app more frequently.  That equals higher app usage, higher ad impressions, etc.  Because the earthquake app is consuming earthquake data on our backend using Windows Azure Mobile Services, it’s trivial to send notifications when new earthquakes are detected.  We can send a nice live tile that looks like so: Clearly, this is better than displaying _nothing_, and the map adds a professional look to it.   We can also combine this with badges – for example, in Dark Skies, I do something similar when users add new locations to the map, adding a badge notification that displays how many new locations are nearby: The first step in doing this is to determine which tile template to use.  Because the map is the main image, this is a pretty simple as we’d want the map to take up the main tile.  The place to look is the tile template catalog on MSDN.  In this case, TileWideImageAndText02 seems to fit the bill for wide tiles, and TileSquareImage is the bet bet for smaller, square-sized tiles.  From the template page: The key here is the tile XML – it’s the same if we’re doing a push notification, if the app is updating its own tile, or if Windows is updating the tile using the TileUpdater using periodic updates.  To get the image, we’ll use the Bing Maps REST API, which requires a valid Bing Maps key from the portal site.  For a wide tile, we can get a static map using a URL like so, specifying the zoom level (2), centered location (36 latitude, –79 longitude), pushpin location (also at 36 latitude, –79 longitude), and a size of 310x100: http://dev.virtualearth.net/REST/v1/Imagery/Map/Road/36,-79/2?mapSize=310,100&pushpin=36,-79;48&key={your_api_key} Which returns an image like so: From the Windows Azure Mobile Service, it’s fairly simple to send a notification with some code like the below.  I’m removing some of the dynamic text to shorten it up a little, but realistically we’d be setting the location of the pin(s) and text of the tile itself dynamically: 1: function sendNotification(channelUri) { 2:   3: var baseImageUrl = "http://dev.virtualearth.net/" + 4: "REST/v1/Imagery/Map/Road/36,-79/2?[mapsize]" + 5: "&pushpin=36,-79;48&key={your_api_key}"; 6: 7: var smallImage = baseImageUrl.replace("[mapsize]", "mapSize=150,150"); 8: var bigImage = baseImageUrl.replace("[mapsize]", "mapSize=310,100"); 9:   10: var payload = "<tile><visual><binding template='TileWideImageAndText02'>" + 11: "<image id='1' src='" + xmlEscape(bigImage) + "' alt='map'/>" + 12: "<text id='1'>Some top line text here</text>" + 13: "<text id='2'>Some bottom line text here</text>" + 14: "</binding>" + 15: "<binding template='TileSquareImage' branding='none'>" + 16: "<image id='1' src='" + xmlEscape(smallImage) + 17: "' alt='map'/></binding></visual></tile>"; 18:   19: var theTag = 'some_identifier'; 20: push.wns.send(channelUri, payload, 'wns/tile', 21: { 22: client_id: 'your ms-app:// id', 23: client_secret: 'your client secret', 24: headers: { 'X-WNS-Tag': theTag } 25: }, 26: function (error, result) { 27: if (error) { 28: console.log("(" + error.statusCode + ") Error sending notification"); 29: } 30: } 31: ); 32: }  .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } (Note: the xmlEscape method is omitted, but is a simple method that escapes special characters for the XML document.)  What we’re doing here is using the push.wns (Windows Notification Service) object to send the tile XML directly.   If you review the script reference, it is certainly simpler to use the push.wns.sendTileWideImageAndText02 method, but I generally prefer to build the XML directly as done above.  The reason is that it allows you to bundle multiple notifications together – such as including both the wide and narrow tile versions.  (The other side benefit is that this allows you to enter the application package ID and secret, which should allow a single WAMS to send notifications to multiple applications.) We’ll look at other mashup examples in future posts!

Creating a Great Mashup Part 2

This post details features used by Earthquake Explorer, a Windows 8 app that displays earthquake information on Bing maps.   Earthquake Explorer was based off of the Earthquakes mashup starter kit on github.  Read part 1 here.  In the first part, we created a Windows Azure Mobile Service to store data as a back end for our mashup.  A big benefit of this approach is that it lets us filter/sort/query the data any way we’d like, and our application is now resilient against outages and changes in the schema.   In this part, we are going to modify our existing scheduled task to consume the actual USGS data feed and store it in a table. Getting the data is simple, thanks to the nice GeoJSON feed provided by the USGS.  Read more about that here: http://earthquake.usgs.gov/earthquakes/feed/v1.0/ From within our scheduled job, we can query it like so: function fetchUSGS() { console.log('Starting job'); var httpRequest = require('request'); var uri = 'http://earthquake.usgs.gov/earthquakes/feed/v0.1/summary/all_hour.geojson'; httpRequest(uri, function (err, response, body) { if (err) { console.warn('Error connecting to service.'); } else if (response.statusCode !== 200) { console.warn('Unexpected reply.'); } else { //got reply, process the results var theData = JSON.parse(response.body); processData(theData); } }); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } We’re making a request to the feed (uri) and specifying the callback as the inline function.   There really isn’t any robust error handling, but then, there really isn’t much you can do in the event of an error except just try again the next time the task runs.  Calling JSON.parse() will, naturally, parse the response text into a nice object collection we can parse.  If we look at the JSON in fiddler, you can see the structure of the document: The JSON contains a collection of features, where each feature contains a geometry object, an id string, and a properties object.  Either through the documentation on the USGS site, or through examining the results, we’ll need to know the structure of the data. To make working with the data a bit easier we can create a simple javascript class to hold the data: function earthquake(item) { this.latitude = item.geometry.coordinates[1]; this.longitude = item.geometry.coordinates[0]; this.depth = item.geometry.coordinates[2]; this.usgsId = item.id; this.usgsCode = item.properties.code; this.tz = item.properties.tz; this.mag = item.properties.mag; this.time = item.properties.time; this.updated = item.properties.updated; this.place = item.properties.place; this.timestamp = new Date(); } The one tricky part here is that the identifier of the earthquake is the USGS ID, but all data in Azure Mobile Services uses a bigint as a primary key.  When we’re updating a row in Mobile Services, we’d pass the object into the update method with the appropriate ID (bigint).  (Deletes require the bigint ID only.)  Yes, this is a slight inefficiency because WAMS uses the surrogate bigint, and the USGS prefers the natural key of the USGS ID, and we will, for simplicity sake, use both depending on the operation.  Because we’re requesting the data frequently, each item in the feed will have one of a few states:  it may be new (not in the database), it may be in the database already, or it may be in the database but the feed contains updated/revised values. function processData(json) { var quakesTable = tables.getTable('earthquakes'); var featureList = json.features; featureList.forEach( function (item) { var eq = new earthquake(item); quakesTable.where({ usgsId: eq.usgsId }).read({ success: function (results) { if (results.length > 0) { //record exists eq.id = results[0].id; eq.timestamp = new Date(); quakesTable.update(eq); } else { //record doesn't exist quakesTable.insert(eq); //send notification? //see next blog post } } }); } ); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } As we iterate through the features, we create an earthquake object from each item.   We then check the table for a record with the same USGS ID property.  If it already exists, we’ll update the row with the information because details may have changed.  Otherwise, we’ll insert it.  There’s a general inefficiency here that we can deal with if we’re so motivated.  Each item results in a query to see if the item exists, and then a query to either update or insert.  We could simply build a stored procedure that handles either scenario so it’s one call, but because each feed contains about 10 items and this scheduled task is a server-side job, it’s not high on my priority list.  With higher volume apps and/or with client apps, this is a modification you should make. The other nice thing we can do is send notifications when a new earthquake is found.  For example, if a new earthquake is found in the feed, we can send a live tile notification which would update the tile to look like so:   For Windows 8 apps, this is really a must-do feature.  Do _something_ (anything!) with the live tile – this will differentiate your app.  Mobile Services can send notifications to Windows Phone, Windows 8, iOS, and Android, so this is a great way to take the app cross platform.  In the next post, we’ll look at how to do a live tile update like the one above.

Microsoft DevRadio: (Part 7) Using Windows Azure to Build Back-End Services for Windows 8 Apps – Authentication Tips and Tricks

At long last!  Our final installment to the series – check it out! About this Video: Wrapping up their  “Using Windows Azure to Build Back-End Services for Windows 8 apps” series Brian Hitney , Andrew Duthie  and Peter Laudati, as they showoff some useful tips and tricks around authentication for your Windows Azure Mobile Server based apps. Tune in as they enable persistent login for a mobile service, and then discuss how we can get additional information about users from the configured identity provider(s).  Check out the full article here. Watch Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 After watching this video, follow these next steps: Step #1 – Try Windows Azure: No cost. No obligation. Start your FREE trial now. Step #2 – Download the Tools for Windows 8 App Development Step #3 – Start building your own Apps for Windows 8 Subscribe to our podcast via iTunes or RSS If you're interested in learning more about the products or solutions discussed in this episode, click on any of the below links for free, in-depth information: Blogs & Articles: Brian Hitney’s blog Peter Laudati’s blog Andrew Duthie’s Blog Article:  “Getting user information on Azure Mobile Services” Article:  “Using Azure Mobile Services authentication” Videos: Microsoft DevRadio: How to Get Started with Windows Azure Microsoft DevRadio: (Part 1) What is Windows Azure Web Sites? Microsoft DevRadio: (Part 2) Windows Azure Web Sites Explained Microsoft DevRadio: How to Integrate TFS Projects with Windows Azure Web Sites Virtual Labs: MSDN Virtual Labs: Windows Azure Download MP3 (Audio only) MP4 (iPod, Zune HD) High Quality MP4 (iPad, PC) Mid Quality MP4 (WP7, HTML5) High Quality WMV (PC, Xbox, MCE)

Microsoft DevRadio: (Part 5) Using Windows Azure to Build Back-End Services for Windows 8 Apps – Adding Push Notifications

Abstract: In Part 5 of of their “Using Windows Azure to Build Back-End Services for Windows 8 apps” series Peter Laudati, Brian Hitney and Andrew Duthie  show us how to quickly add the ability to implement push notifications for his GameLeader Service using Azure Mobile Services. Check out the full article here. Watch Part 1 | Part 2 | Part 3 | Part 4 After watching this video, follow these next steps: Step #1 – Try Windows Azure: No cost. No obligation. 90-Day FREE trial. Step #2 – Download the Tools for Windows 8 App Development Step #3 – Start building your own Apps for Windows 8 Subscribe to our podcast via iTunes or RSS If you're interested in learning more about the products or solutions discussed in this episode, click on any of the below links for free, in-depth information: Register for our Windows Azure Hands-on Lab Online (HOLO) events today! Windows Azure Hands-on Labs Online Blogs: Brian Hitney’s blog Peter Laudati’s blog Andrew Duthie’s Blog Videos: Microsoft DevRadio: How to Get Started with Windows Azure Microsoft DevRadio: (Part 1) What is Windows Azure Web Sites? Microsoft DevRadio: (Part 2) Windows Azure Web Sites Explained Microsoft DevRadio: How to Integrate TFS Projects with Windows Azure Web Sites Virtual Labs: MSDN Virtual Labs: Windows Azure Download MP3 (Audio only) MP4 (iPod, Zune HD) High Quality MP4 (iPad, PC) Mid Quality MP4 (WP7, HTML5) High Quality WMV (PC, Xbox, MCE)

Dealing with Expired Channels in Windows Azure Mobile Services

What’s this?  Another Windows Azure Mobile Services (WAMS) post?!  In the next version of my app, I keep a record of the user’s Channel in order to send down notifications.  The built in todo list example does this or something very similar.  My table in WAMS looks like: Not shown are a couple of fields, but of particular interest is the device Id.  I realized that one user might have multiple devices, so the channel then is tied to the device Id.  I still haven’t found a perfect way to do this yet – right now, I’m using a random GUID on first run.  In my WAMS script, if the point that is submitted is “within range” of another user, we’ll send a notification down to update the tile.  I go into this part in my blog post:  Best Practices on Sending Live Tiles.    But what do you do if the channel is expired?  This comes up a lot in testing, because the app is removed/reinstalled many times.  I stumbled on this page, Push Notification Service Request and Response Headers,  on MSDN.   There is a lot of great info on that page.   While I should have more robust solution for handling all these conditions, the one in particular I’m interested in is the Channel Expired response, highlighted below: HTTP response code Description Recommended action 200 OK The notification was accepted by WNS. None required. 400 Bad Request One or more headers were specified incorrectly or conflict with another header. Log the details of your request. Inspect your request and compare against this documentation. 401 Unauthorized The cloud service did not present a valid authentication ticket. The OAuth ticket may be invalid. Request a valid access token by authenticating your cloud service using the access token request. 403 Forbidden The cloud service is not authorized to send a notification to this URI even though they are authenticated. The access token provided in the request does not match the credentials of the app that requested the channel URI. Ensure that your package name in your app's manifest matches the cloud service credentials given to your app in the Dashboard. 404 Not Found The channel URI is not valid or is not recognized by WNS. Log the details of your request. Do not send further notifications to this channel; notifications to this address will fail. 405 Method Not Allowed Invalid method (GET, DELETE, CREATE); only POST is allowed. Log the details of your request. Switch to using HTTP POST. 406 Not Acceptable The cloud service exceeded its throttle limit. Log the details of your request. Reduce the rate at which you are sending notifications. 410 Gone The channel expired. Log the details of your request. Do not send further notifications to this channel. Have your app request a new channel URI. 413 Request Entity Too Large The notification payload exceeds the 5000 byte size limit. Log the details of your request. Inspect the payload to ensure it is within the size limitations. 500 Internal Server Error An internal failure caused notification delivery to fail. Log the details of your request. Report this issue through the developer forums. 503 Service Unavailable The server is currently unavailable. Log the details of your request. Report this issue through the developer forums. Obviously getting a new channel URI is ideal, but the app has to do that on the client (and will) next time the user runs the app.  In the mean time, I want to delete this channel because it’s useless.   In my script which sends the notifications, we’ll examine the result on the callback and either delete the channel if expired, or, if success, send a badge update because that’s needed, too.  (Future todo task: try to combine Live Tile and badges in one update.) push.wns.send(channelUri, payload, 'wns/tile', { client_id: 'ms-app://<my app id>', client_secret: 'my client secret', headers: { 'X-WNS-Tag' : 'SomeTag' } }, function (error, result) { if (error) { //if the channel has expired, delete from channel table if (error.statusCode == 410){ removeExpiredChannel(channelUri) } } else { //notification sent updateBadge(channelUri); } } ); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Removing expired channels can be done with something like: function removeExpiredChannel(channelUri) { var sql = "delete from myapp.Channel where ChannelUri = ?"; var params = [channelUri]; mssql.query(sql, params, { success: function(results) { console.log('Removed Expired Channel: ' + channelUri) } }); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } On my todo list is to add more robust support for different response codes – for example, in addition to a 410 response, a 404 would also want to delete the channel record in the table.

Calling Stored Procedures from Windows Azure Mobile Services

I was surprised, yet delighted, that Windows Azure Mobile Services uses a SQL database.   Schema-less table storage has its place and is the right solution at times, but for most data driven applications, I’d argue otherwise. In my last post, I wrote about sending notifications by writing the payload explicitly from a Windows Azure Mobile Service.   In short, this allows us to include multiple tiles in the payload, accommodating users of both wide and square tiles.   In my application, I want to execute a query to find push notification channels that match some criteria.  If we look at the Windows Azure Mobile Services script reference, the mssql object allows us to query the database using T-SQL and parameters, such as: mssql.query('select top 1 * from statusupdates', { success: function(results) { console.log(results); } }); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }In my case, the query is a bit more complicated.  I want to join another table and use a function to do some geospatial calculations – while I could do this with inline SQL like in the above example, it’s not very maintainable or testable.  Fortunately, calling a stored procedure is quite easy. Consider the following example:  every time the user logs in, the Channel URI is updated.  What I’d like to do is find out how many new locations (called PointsOfInterest) have been modified since the last time the user has logged in.  To do that, I have a stored procedure like so: create procedure [darkskies].[NewLocationsForChannel] ( @channelUri as nvarchar(512) = null ) as select c.ChannelUri, count(1) as NumNewLocations from darkskies.Channel c inner join darkskies.PointOfInterest p on c.UserId = p.UserId where p.LastUpdated > c.LastUpdated and c.ChannelUri = @channelUri group by c.ChannelUri .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Writing something like that inline to the mssql object would be painful.   As a stored procedure, it’s much easier to test and encapsulate.  In my WAMS script, I’ll call that procedure and send down a badge update: function updateBadge(channelUri) { var params = [channelUri]; var sql = "exec darkskies.NewLocationsForChannel ?"; mssql.query(sql, params, { success: function(results) { if (results.length > 0) { for (var i=0; i< results.length; i++) { if (results[i].ChannelUri !== null && results[i].ChannelUri.length > 0) { push.wns.sendBadge(results[i].ChannelUri, results[i].NumNewLocations); } } } } }); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }This section of code only updates the badge of the Windows 8 Live Tile, but it works out nicely with tile queuing: Note: this app is live in the Windows 8 Store, however, at the time of this writing, these features have not yet been released.  In the next few posts, we’ll look at the notifications a bit more, including how to pull off some geospatial stuff in WAMS.

Best Practice for Sending Windows 8 Tiles from Mobile Services

Those that know me know I am not a fan of javascript, in pretty much all of its forms (including node.js), however, I’m really digging Windows Azure Mobile Services (WAMS).  WAMS allows you to easily provide a back end to applications for storing data, authenticating users, and supporting notifications on not just Windows and Windows Phone, but also iOS with future plans of supporting Android soon. Now, I mention javascript because WAMS provides a slick node-like powered data service that makes it really easy to store data in the cloud.  The ToDoList example exercise illustrates the ease at storing user data in the cloud and hooking it up with authentication and notification support.   The nice thing about the authentication is that it’s easily integrated into the backend: But, more on this later.  Right now, I want to deal with notifications in WAMS.  In WAMS, you have the opportunity to right custom server-side javascript to do things like send notifications on insert/update/delete/read access: In my case, I want to send a tile update if the new data meets some criteria.   Let’s start all the way down the code and work our way out, starting with the notification piece.    One page you MUST have bookmarked is the tile template catalog on MSDN.   This page defines the XML syntax for all possible tiles your tile can have, including both small/square tiles, and large/wide tiles.    All of these have a defined schema, such as this for TileSquarePeekImageAndText04: <tile> <visual> <binding template="TileSquarePeekImageAndText04"> <image id="1" src="image1" alt="alt text"/> <text id="1">Text Field 1</text> </binding> </visual> </tile> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Which produces a tile that “peeks”, such as this (which flips between the top half and bottom half): Yes, it’s easy to laugh at the magic “04” in the template title.  I like to joke that my personal favorite is TileWideSmallImageAndText03.   But, there variety is crucial to creating the ideal app experience and that depends on how you want to display the data -- and that requires knowing the XML template. Now, in WAMS, there’s a great tutorial on sending some basic notifications.   In that walkthrough, a notification is sent via the server-side javascript like so: push.wns.sendTileSquareText02(“https://bn1.notify.windows.com?[snip]”, { text1: “some text”, text2: “more text”}); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Now, at first glance, this is very nice because WAMS will write the XML for you.  However, you still must know what data the template requires.  Does it need an image?  One text line?  Two?   You get the point.  Unsurprisingly, calling that method will generate XML like: <tile> <visual> <binding template="TileSquareText02"> <text id="1">some text</text> <text id="2">more text</text> </binding> </visual> </tile> You can learn more about this in the WAMS script reference.  Another must-have bookmark.  However, I recommend you don’t use these at all, and instead write the XML payload directly.   This is for a few reasons, but primarily, it’s for control – and, really, you have to know the fields required anyway and you’ll still have the tile catalog page open for reference. In looking at the mpns (Microsoft Push Notification Service) library a bit closer (awesome job by the guys, by the way) up on git, it has this method: var raw = new mpns.rawNotification('My Raw Payload', options); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } When developing my app, I realized I had no idea what tile size the user has.   Some may opt to use a wide tile, others a small tile.  I needed different tiles to support both.   I didn’t like sending two notifications (seems wasteful, doesn’t it?) and to do this efficiently, it’s easier to just create the payload explicitly that includes all tiles.  For example, this includes two completely different tiles: var payload = "<tile><visual><binding template='TileWideImageAndText02'>" + "<image id='1' src='" + xmlEscape(bigImage) + "' alt='map'/>" + "<text id='1'>" + text1 + "</text>" + "<text id='2'>" + text2 + "</text>" + "</binding>" + "<binding template='TileSquareImage' branding='none'>" + "<image id='1' src='" + xmlEscape(smallImage) + "' alt='map'/></binding></visual></tile>"; push.wns.send(channelUri, payload, 'wns/tile', { client_id: 'ms-app://<snip>', client_secret: 'i will never tell', headers: { 'X-WNS-Tag' : 'MainTile' } }... .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Sure, it doesn’t look as clean and (gasp!) we have to do string concatenation.   But, it’s only a couple of minutes more work and just more flexible.  Like I said: either way, you need to know the template.   In my case, I’m sending both notifications in one payload.  The first is TileWideImageAndText02, which produces a nice image with the text on the bottom describing the image.  If the user has a small tile, it will use TileSquareImage, which basically just forgoes the text and just displays the image.  After trying a few, I settled on this combination as the best user experience.  This is an easy way, with minimal effort, to support both wide and narrow tiles. As an aside, I recommend setting the tag (X-WNS-Tag) header, particularly if your app cycles tiles and you want to replace a specific tile.  Also, it’s a good ideal to XML escape all data, which I’m doing with the long image URLs … and this, I believe, is taken right from the mpns library: var xmlEscape = function (text) { return text.replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;'); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } If you don’t escape the data and have some illegal chars in there as a result, the notification gets sent correctly (that is, accepted), but gets ignored by the client. Now that I’ve got the basic code to send a tile, I needed to filter some data and run a query and sort users by distance.  Sound like fun?  I’ll write about that next…

My Apps

Dark Skies Astrophotography Journal Vol 1 Explore The Moon
Mars Explorer Moons of Jupiter Messier Object Explorer
Brew Finder Earthquake Explorer Venus Explorer  

My Worldmap

Month List