Updated NotificationsExtensions WnsRecipe Nuget to support Windows 8.1 templates now available

A short post to let you know that I have just published the updated NotificationsExtensions WnsRecipe Nuget with support for the new notification templates that were added in Windows 8.1.

Here is a short demonstration of how to use it to send a new TileSquare310x310ImageAndText01 template with the WnsRecipe Nuget Package

Install the package using Nuget Package Manager Console. (Note you could also do this using Manage package references in solution explorer)

install-package WnsRecipe

Add using statements to the NotificationsExtensions namespace

using NotificationsExtensions;
using NotificationsExtensions.TileContent;

New up a new WnsAccessTokenProvider and provide it your credentials configured in the Windows Store app Dashboard

private WnsAccessTokenProvider _tokenProvider = new WnsAccessTokenProvider("ms-app://", "");

Use Tile Content Factory to create your tile template

var tile = TileContentFactory.CreateTileSquare310x310ImageAndText01();

tile.Image.Src = "https://nickha.blob.core.windows.net/tiles/empty310x310.png";
tile.Image.Alt = "Images";
tile.TextCaptionWrap.Text = "New Windows 8.1 Tile Template 310x310";

// Note you really should not do the line below :) , 
// instead you should be setting the required content 
// through property tile.Wide310x150Content so that users
// get updates irrespective of what size tile they have pinned to Start
tile.RequireWide310x150Content = false;  

//Send the notification to the desired channel
var result = tile.Send(new Uri(channel), _tokenProvider);

and here is the output
310x310tile

Enjoy, Nick Harris

Execute Scheduled Scripts with the New Windows Azure Mobile Services Scheduler

In this post I will demonstrate how you can poll twitter on a scheduled basis for tweets directed at an alias and then use this information to send a Push Notification in the form of a Tile update.  But first lets talk about What’s new for Windows Azure Mobile Services

What was Announced Today!

Today, Scott Guthrie announced  updates to Windows Azure Mobile Services which allows developers to take advantage of the cloud to build and deploy modern apps for Windows 8 and iOS.  Whether you are a developer building for the Windows Store, Windows Phone 8, iPhone, or iPad, Mobile Services provides an easy, streamlined process for backend elements like storing structured data, configuring user authentication via Windows Live, Facebook, Twitter, and Google, and incorporating push notifications.

If you are building a mobile application Windows Azure Mobile Services can help in the following ways:

  • Rapid Development: configure a straightforward and secure backend for Windows 8 and mobile applications in less than five minutes.
  • Create modern mobile app with built in support and new added capabilities:
  • (NEW)Scheduled Scripts: run a server script on a pre-set schedule or on-demand which enables several key scenarios including:
    • aggregating data from Twitter, RSS feeds, or any external web services
    • executing background code efficiently, such as process/resize images, performing complex calculations, or sending emails
    • schedule sending push notifications to customers to ensure they arrive at the right time of day
  • (NEW) Command-line support: use the Windows Azure cross platform command line tools to easily create and manage mobile services
  • (NEW) Availability in Europe: create Mobile Services in the North Europe region in addition to the US East and US West regions

Getting Started with Scheduled Scripts with the Windows Azure Mobile Services Scheduler

In this section I will demonstrate how you can poll twitter on a scheduled basis for tweets directed at an alias and then use this information to send a Push Notification in the form of a Tile update.  This is a simplified version of Yavor’s post here - if you want to see how you can filter tweets and take this a bit further jump over to Yavor’s blog and check it out.

    1. Create the scheduler job that will send push notifications to registered clients every 15 minutes with the latest Twitter updates for a particular twitter handle.
    2. Specify a name for the job and make sure the schedule frequency is set to every 15 minutes. Click the check mark to create the job.

    1. Select the created job from the job list.
    2. Select the Script tab and paste the code snippet below that both polls Twitter and then composes a push notification to update your start screens tile using push.wns.*
      1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
      function CheckFeed() {
      getUpdatesAndNotify();
      }
       
      var request = require('request');
      function getUpdatesAndNotify() {
      request('http://search.twitter.com/search.json?q=@cloudnick&rpp=2',
      function tweetsLoaded (error, response, body) {
      var results = JSON.parse(body).results;
      if(results){
      results.forEach(function visitResult(tweet){
      sendNotifications(tweet);
      });
      }
      });
      }
       
      function sendNotifications(tweet){
       
      var channelTable = tables.getTable('Channel');
      channelTable.read({
      success: function(channels) {
      channels.forEach(function(channel) {
       
      push.wns.sendTileWideSmallImageAndText04(channel.uri, {
      image1src: tweet.profile_image_url,
      text1: '@' + tweet.from_user,
      text2: tweet.text
      });
       
      });
      }
      });
      }
      view raw gistfile1.js hosted with ❤ by GitHub
    3. Once you paste the script into the editor, click the Save button to store the changes to the script.
    4. In Visual Studio, press F5 to build and run the application.  This will ensure your channel URI is up to date and will ensure the Default Wide tile is now on your Start screen
    5. Go back to the Windows Azure Management Portal, select the Scheduler tab of your mobile service, and then click Enable in the command bar to allow the job to run

.

  1. To test your script immediately rather than wait 15 minutes for it to be scheduled, click Run Once in the command bar.
  2. Return to the start screen and see the latest update on your application tile

Summary

In this post you learnt how you can use the Windows Azure Mobile Services Scheduler to execute scripts on a scheduled basis.  We used scheduled scripts to poll twitter every 15 minutes and send a push notification in the form of a Live Tile to our windows store apps with the latest tweets at an alias.

Here are some related resources you should checkout:

You can get started today with 10 Mobile Services for FREE

 

How to upload an Image to Windows Azure Storage using Mobile Services

This post details how to use the Windows Azure SDK for Node from Windows Azure Mobile Services to generate a Shared Access Signature (SAS) and then how to upload your Image (or any file) to Blob Storage directly from your Windows Store App using the Windows Azure Storage Client Library 2.0 for Windows Runtime (CTP)

Background

In my previous post How to Upload an Image using a Blob Storage SAS generated by Windows Azure Mobile Services I detailed:

  1. Why you should use a SAS to upload any binary data from client devices
  2. How you could generate your own SAS using Mobile Services Server Side scripts
  3. How you could use the HttpClient from a Windows Store app to upload your image using the SAS

With the recent inclusion of the Windows Azure SDK for Node in Mobile Services and the announcement of the Windows Azure Storage Client Library 2.0 for Windows Runtime (CTP) the process for performing Steps 2 and 3 are much easier.  This post will detail the updated approach.

Creating your Mobile Service

In this post I will extend the Mobile Services quick start sample. Before proceeding to the next section create a mobile service and download the quickstart as detailed in the tutorial here

Capturing the Image|Media

Our first task is to capture the media we wish to upload. To do this follow the following steps.

  • Add an AppBar to MainPage.xaml with a take photo button to allow us to capture the image
1 2 3 4 5 6 7 8 9 10 11
...
</Grid>
...
<Page.BottomAppBar>
<AppBar>
<Button Name="btnTakePhoto" Style="{StaticResource PhotoAppBarButtonStyle}"
Click="OnTakePhotoClick" />
</AppBar>
</Page.BottomAppBar>
...
</Page>
view raw gistfile1.cs hosted with ❤ by GitHub
  • Add the OnTakePhotoClick handler and use the CameraCaptureUI class for taking photo and video
1 2 3 4 5 6 7 8 9 10 11
using Windows.Media.Capture;
 
 
private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
{
//Take photo or video
CameraCaptureUI cameraCapture = new CameraCaptureUI();
StorageFile media = await cameraCapture.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
 
 
}
view raw gistfile1.cs hosted with ❤ by GitHub
  • Update the TodoItem class with some properties that will be required to generate the SAS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
public class TodoItem
{
public int Id { get; set; }
 
[DataMember(Name = "text")]
public string Text { get; set; }
 
[DataMember(Name = "complete")]
public bool Complete { get; set; }
 
//Added below for blob sas generation in Mobile Services
 
[DataMember(Name = "containerName")]
public string ContainerName { get; set; }
 
[DataMember(Name = "resourceName")]
public string ResourceName { get; set; }
public string SAS { get; set; }
 
}
view raw gistfile1.cs hosted with ❤ by GitHub
  • Update the OnTakePhotoClick handler to insert the todoitem setting the ContainerName and resourceName for which we want a SAS generated
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
{
//Take photo or video
CameraCaptureUI cameraCapture = new CameraCaptureUI();
StorageFile media = await cameraCapture.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
 
//add todo item to trigger insert operation which returns item.SAS
var todoItem = new TodoItem() {
ContainerName = "mypics",
ResourceName= media.Name,
Text = "NA",
};
 
await todoTable.InsertAsync(todoItem);
items.Add(todoItem);
 
//TODO: Upload image direct to blob storage using SAS
}
view raw gistfile1.cs hosted with ❤ by GitHub

Generating a Shared Access Signature (SAS) using Mobile Services server-side script

In this step we add sever-side script to generate a SAS on insert operation of the TodoItem table.

To do this perform the following steps:

  • Navigate to your Mobile Service and select the Data Tab, then click on Todoitem

  • Select Script, then the Insert drop down

  • Add the following server side script to create the containerName and generate a blob SAS for the resourceName
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
var azure = require('azure');
var qs = require('querystring');
 
function insert(item, user, request) {
var accountName = '<replace with your storage account name>';
var accountKey = '<replace with your storage account key>';
var host = accountName + '.blob.core.windows.net';
var canonicalizedResource = '/' + item.containerName + '/' + item.resourceName;
//Must be lowercase
item.containerName = item.containerName.toLowerCase();
//Create the container if it does not exist
//we will use public read access for the blobs and will use a SAS to upload
var blobService = azure.createBlobService(accountName, accountKey, host);
blobService.createContainerIfNotExists(item.containerName, {publicAccessLevel : 'blob'}, function(error){
if(!error){
// Container exists now define a policy that provides write access
// that starts immediately and expires in 5 mins
var sharedAccessPolicy = {
AccessPolicy:{
Permissions: azure.Constants.BlobConstants.SharedAccessPermissions.WRITE,
//Start: //use for start time in future, beware of server time skew
Expiry: formatDate(new Date(new Date().getTime() + 5 * 60 * 1000)) //5 minutes from now
}
};
//Generate the SAS for your BLOB
var sasQueryString = getSAS(accountName,
accountKey,
canonicalizedResource,
azure.Constants.BlobConstants.ResourceTypes.BLOB,
sharedAccessPolicy);
//full path for resource with sas
item.sas = 'https://' + host + canonicalizedResource + '?' + sasQueryString;
}
else{
console.error(error);
}
request.execute();
});
}
 
function getSAS(accountName, accountKey, path, resourceType, sharedAccessPolicy) {
return qs.encode(new azure.SharedAccessSignature(accountName, accountKey)
.generateSignedQueryString(path, {}, resourceType, sharedAccessPolicy));
}
 
function formatDate(date){
var raw = date.toJSON();
//blob service does not like milliseconds on the end of the time so strip
return raw.substr(0, raw.lastIndexOf('.')) + 'Z';
}
view raw gistfile1.js hosted with ❤ by GitHub

Using the Windows Azure Storage Client Library 2.0 for Windows Runtime (CTP) to upload the Image directly to storage using the SAS

  • Download the Storage Client libraries for Windows 8 click here.
  • Extract and add a reference to Microsoft.WindowsAzure.Storage.winmd your client project
  • Update OnTakePhotoClick handler to update the image directly to blob storage using the CloudBlockBlob,UploadFromStreamAsync and the generated todoitem.SAS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
...
 
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
 
...
 
private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
{
//Take photo or video
CameraCaptureUI cameraCapture = new CameraCaptureUI();
StorageFile media = await cameraCapture.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
 
if (media != null)
{
//add todo item to trigger insert operation which returns item.SAS
var todoItem = new TodoItem()
{
ContainerName = "mypics",
ResourceName = media.Name,
Text = "NA",
};
await todoTable.InsertAsync(todoItem);
items.Add(todoItem);
 
//Upload image direct to blob storage using SAS and the Storage Client library for Windows CTP
//Get a stream of the image just taken
using (var fileStream = await media.OpenStreamForReadAsync())
{
var sasUri = new Uri(todoItem.SAS);
 
//Our credential for the upload is our SAS token
StorageCredentials cred = new StorageCredentials(sasUri.Query.Substring(1));
CloudBlobContainer container = new CloudBlobContainer(new Uri(string.Format("https://{0}/{1}", sasUri.Host, todoItem.ContainerName)), cred);
CloudBlockBlob blobFromSASCredential = container.GetBlockBlobReference(todoItem.ResourceName);
await blobFromSASCredential.UploadFromStreamAsync(fileStream.AsInputStream());
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

Run the application

  • Hit F5 on the application and right click with your mouse to show the app bar
  • Press the Take Photo button
  • Observe that the SAS is returned from your Mobile Service

  • Check your storage account now has a great picture of a fully polished chrome dome capable of reflecting light far better then your average mirror :)

Enjoy,
Nick

Blog Series: Sending Windows 8 Push Notifications using Windows Azure Mobile Services

Sending Windows 8 Push Notifications using Windows Azure Mobile Services

Recently we announced the preview of Windows Azure Mobile Services. In this blog series I will detail how to build a Windows Azure Mobile Service to send push notifications of varying types to your Windows 8 applications.

This series will walk through creating a push notification scenario using WNS and Windows Azure Mobile Services.

As I post each part I will update the links below and tweet as the post is available. So lets get started with Part 1 - Azure Mobile Services and Push Notifications an Overview

Part 1: Windows Azure Mobile Services and Push Notifications an Overview

What is Windows Azure Mobile Services?

Here is an info-graphic on the current Windows Azure Mobile Services stack I pulled together as part of a presentation I recently gave at TechEd.  It’s important to note that this info-graphic captures Mobile Services today and over time you will see the feature set of Mobile Services grow exponentially with subsequent releases.

 

 

 

 

 

 

 

 

 

 

The goal of Windows Azure Mobile Services is to make it incredibly easy for developers to add a cloud backend to their client apps be it a Windows 8, Windows Phone, iOS or Android application. To do this we provide a number of turn key features baked right into the Mobile Services experience. As the diagram depicts Mobile Services today provides:

  • Structured Storage
    • ability to store structured data to a SQL Database using dynamic schema without being concerned with writing underlying T-SQL.
    • If using single database apps are automatically partitioned by schema e.g AppX.Todoitem, AppY.Todoitem
    • If you want access to your data you are not locked out and can manage it in a number of ways including the Mobile Service Portal, SQL Portal, SQL Management Studio, REST API etc.
  • Server Logic
    • Service API: Mobile services automatically generates a REST API to allow you to perform CRUD operations from your client application on your structured storage
    • With Dynamic Schema (enabled by default), your Mobile Service will automatically add columns to tables as necessary to store incoming data.
    • Ability to author server side business logic directly in the portal that is executed directly within the CRUD operation pipeline
  • Auth
    • Makes it easy for your users to Authenticate against Windows Live. Other major identity providers are coming soon.
    • The REST API can be locked down using table level permissions using a simple drop down.  No complex code required.  Available permissions levels include: Everyone, Anyone with an Application Key, Only Authenticated Users, Only Scripts and Admins.  These permissions can be set individually on each table and can granularly control each CRUD operation of each table.
    • More granular control can be added using server side scripts and the user object
  • Push Notifications
    • Integrates with WNS to provide Toast, Tile and Badge Notifications.
    • WNS auth is made easy with the portal captures your WNS client secret and package SID
    • the server side script push.wns.* namespace  performs WNS auth for you and provides a clean and easy object model to compose notifications
  • Common tenants of Windows Azure Services
    • Scale
      • Compute - scale between shared and reserved mode, increase/decrease your instance count
      • Storage - ability to scale out your mobile service tenant(s) to a dedicated SQL DB. Ability to scale up your SQL DB from web through business to 150GB.
    • Diagnostics
      • View diagnostics directly in the portal including API calls, CPU time and Data Out
    • Logging
      • Console.* operations like console.log and console.error provide an easy means to debug your server side scripts.

Today we provide client libraries for Windows 8 to make consuming mobile services easy.  For more details on what client libraries (Windows 8, Windows Phone, iOS and Android) are supported at the time of reading please see: Mobile Services and Mobile Service Reference.

What are Push Notifications?

The Windows Push Notification Services (WNS) enables you to send toast, tile, badge and raw notifications from the cloud to your Windows Store applications even when your app is not running. Push notifications are ideal for scenarios when you need to target a specific user with personalized content.

The following diagram depicts the general Lifecycle of a push notifications via the Windows Azure Notification Service (WNS).  We’ll walk through the steps shortly but before doing so I thought it would be important to call out that as a developer implementing a push notification scenario all you need to do is implement those interactions in grey and the applications/services in blue.  Fortunately Mobile Services makes a great deal of this easy for you as you will see throughout the reset of this series. 

The process of sending a push notification boils down to three basic steps:

  • 1. Request a channel. Utilize the WinRT API to request a Channel Uri from WNS.  The Channel Uri will be the unique identifier you use to send notifications to your application.
  • 2. Register the channel with your Windows Azure Mobile Service.  Once you have your channel you can then store your channel and associate it with any application specific data (e.g user profiles and such) until your services decide that it’s time to send a notification to the given channel.
  • 3. Authenticate and Push Notification to WNS. To send notifications to your channel URI you are first required to Authenticate against WNS using OAuth2 to retrieve a token to be used for each subsequent notification that you push to WNS once you have this you can compose and push the notification to the channel recipient. The push.wns.* methods make this task exceptionally quick to accomplish compared to writing it all from scratch yourself.

All in all Windows Azure Mobile Services makes all these concepts and steps and incredibly simple to implement though its structured storage and push notifications features.  This series will walk through creating a push notification scenario using WNS and Windows Azure Mobile Services.

As I post each part I will update the links below and tweet as the post is available

Enjoy,

Nick

Localized Windows Azure Mobile Services Deck, HOL and Demo script

For those of you looking for localized content be it to help you get started with learning about Windows Azure Mobile Services or even if you want to go out and present about it in your local community we have made available a localized hands on labs, powerpoint decks and demo scripts

As a preview here is a screenshot of one of the Agenda slide from the Chinese zh-TW poser point deck

We have localized the content into the following languages thus far.  You can click on the link to get access to the content directly

· Chinese zh-TW
· English en-US
· German de-DE
· French fr-FR
· Italian it-IT
· Japanese ja-JP
· Korean ko-KR
· Portuguese pt-BR

Coming soon:
· Spanish
· Russian

 

Enjoy,
Nick Harris

Windows 8 How to upload an Image using a Blob Storage SAS generated by Windows Azure Mobile Services

Updated: Please read the Background on Shared Access Signatures from this post then move to this updated post – How to upload an Image to Windows Azure Storage using Mobile Services – that will show you how to make use of the Windows Azure Storage SDK for Node.

Windows 8 How to upload an Image using Blob Storage SAS generated by Windows Azure Mobile Services

This post details the specific scenario on how to capture an image on windows 8 and upload it directly to Windows Azure Blob Storage using a Shared Access Signature (SAS) generated within Windows Azure Mobile Services. It demonstrates and alternative approach suited for larger scale implementations (i.e using a SAS) when contrasted with the following article Storing Images from Android in Windows Azure Mobile Services

Note: This topic is advanced and assumes that you have a good knowledge of the Windows Azure Blob REST API and Windows Azure Mobile Services. I would suggest you check out the following tutorials and Blob Storage REST API prior to starting
Note: that although this is specifically an image example you could upload any media/binary data to blob storage using the same approach.

Background – Shared Access Signature

What Are Shared Access Signatures?

A Shared Access Signature is a URL that grants access rights to containers, blobs, queues, and tables. By specifying a Shared Access Signature, you can grant users who have the URL access to a specific resource for a specified period of time. You can also specify what operations can be performed on a resource that’s accessed via a Shared Access Signature. In the case of Blobs operations include:

  • Reading and writing page or block blob content, block lists, properties, and metadata
  • Deleting, leasing, and creating a snapshot of a blob
  • Listing the blobs within a container

Why not just use the storage account name and key directly?

There are a few standout reasons:

  • Security – When building device applications you should not store your storage account name and key within the device app. The reason is that it makes your storage account susceptible to being misused. If someone were to reverse engineer your application take your storage account key then they would essentially have access to 100TB of cloud based storage until such a time that you realized and reset the key. The safer approach is to use a SAS as it provides a time boxed token with defined permissions to a defined resource. With policies the token can also be invalidated/revoked
  • Scale Out (and associated costs)- A common approach I see is uploading an image directly through their web tier e.g a Web API or Mobile Service unfortunate consequence of this at scale is that you are unnecessarily loading your web tier. Consider that each of your instances on your web tier has a limited network I/O. Uploading images directly through this will result in maxing out that I/O and the need to scale out (add more instances) much sooner then alternative approaches. Now consider a scenario where your application requests only a SAS from your web tier you have now moved MBs or image load off your web tier and instead replaced it with a small ~ 100 – 200 byte SAS. This essentially means a single instance now will provide much more throughput and your upload I/O now directly hits the Blob storage service

What is the general workflow for uploading a blob using a SAS?

The four basic steps required when uploading an image using the SAS approach depicted are as follows:

  1. Request a SAS from your service
  2. SAS returned from your service
  3. Upload blob (image/video/binary data) directly to Blob Storage using the SAS
  4. Storage service returns response

For this post we will focus specifically on how to write/upload a blob using a shared access signature that is generated in the mobile service insert trigger.

Creating your Mobile Service

In this post I will extend the Mobile Services quick start sample. Before proceeding to the next section create a mobile service and download the quickstart as detailed in the tutorial here

Capturing the Image|Media

Our first task is to capture the media we wish to upload. To do this follow the following steps.

  1. Add an AppBar to MainPage.xaml with a take photo button to allow us to capture the image
  2. 1 2 3 4 5 6 7 8 9 10 11
    ...
    </Grid>
    ...
    <Page.BottomAppBar>
    <AppBar>
    <Button Name="btnTakePhoto" Style="{StaticResource PhotoAppBarButtonStyle}"
    Click="OnTakePhotoClick" />
    </AppBar>
    </Page.BottomAppBar>
    ...
    </Page>
    view raw gistfile1.cs hosted with ❤ by GitHub
  3. Add the OnTakePhotoClick handler and use the CameraCaptureUI class for taking photo and video
  4. 1 2 3 4 5 6 7 8 9 10 11
    using Windows.Media.Capture;
     
     
    private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
    {
    //Take photo or video
    CameraCaptureUI cameraCapture = new CameraCaptureUI();
    StorageFile media = await cameraCapture.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
     
     
    }
    view raw gistfile1.cs hosted with ❤ by GitHub

Generating a Shared Access Signature (SAS) using Mobile Services server-side script

In this step we add sever-side script to generate a SAS on insert operation of the TodoItem table.

To do this perform the following steps:

  1. Navigate to your Mobile Service and select the Data Tab, then click on Todoitem
  2. Select Script, then the Insert drop down
  3. Add the following server side script to generate the SAS
  4. Note: this code assumes there is already a public container called test.
    Note:Simple example of Generating a Windows Azure blob SAS in Node created using the guidance here.

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    //Simple example of Generating a Windows Azure blob SAS in Node created using the guidance at http://msdn.microsoft.com/en-us/library/windowsazure/hh508996.aspx.
    //If your environment has access to the Windows Azure SDK for Node (https://github.com/WindowsAzure/azure-sdk-for-node) then you should use that instead.
     
     
    function insert(item, user, request) {
    var accountName = '<Your Account Name>';
    var accountKey = '<Your Account Key>';
    //Note: this code assumes the container already exists in blob storage.
    // If you wish to dynamically create the container then implement guidance here - http://msdn.microsoft.com/en-us/library/windowsazure/dd179468.aspx
    var container = 'test';
    var imageName = item.ImageName;
    item.SAS = getBlobSharedAccessSignature(accountName, accountKey, container, imageName);
    request.execute();
    }
     
     
    function getBlobSharedAccessSignature(accountName, accountKey, container, fileName){
    signedExpiry = new Date();
    signedExpiry.setMinutes(signedExpiry.getMinutes() + 30);
    canonicalizedResource = util.format(canonicalizedResource, accountName, container, fileName);
    signature = getSignature(accountKey);
    var queryString = getQueryString();
    return util.format(resource, accountName, container, fileName, queryString);
    }
     
     
    function getSignature(accountKey){
    var decodedKey = new Buffer(accountKey, 'base64');
    var stringToSign = signedPermissions + "\n" + signedStart + "\n" + getISO8601NoMilliSeconds(signedExpiry) + "\n" + canonicalizedResource + "\n" + signedIdentifier + "\n" + signedVersion;
    stringToSign = stringToSign.toString('UTF8');
    return crypto.createHmac('sha256', decodedKey).update(stringToSign).digest('base64');
    }
     
     
    function getQueryString(){
    var queryString = "?";
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNED_VERSION, '2012-02-12');
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNED_RESOURCE, signedResource);
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNED_START, getISO8601NoMilliSeconds(signedStart));
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNED_EXPIRY, getISO8601NoMilliSeconds(signedExpiry));
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNED_PERMISSIONS, signedPermissions);
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNATURE, signature);
    queryString += addEscapedIfNotNull(queryString, Constants.SIGNED_IDENTIFIER, signedIdentifier);
    return queryString;
    }
     
     
    function addEscapedIfNotNull(queryString, name, val){
    var result = '';
    if(val)
    {
    var delimiter = (queryString.length > 1) ? '&' : '' ;
    result = util.format('%s%s=%s', delimiter, name, encodeURIComponent(val));
    }
    return result;
    }
     
     
    function getISO8601NoMilliSeconds(date){
    if(date)
    {
    var raw = date.toJSON();
    //blob service does not like milliseconds on the end of the time so strip
    return raw.substr(0, raw.lastIndexOf('.')) + 'Z';
    }
    }
     
     
    var Constants = {
    SIGNED_VERSION: 'sv',
    SIGNED_RESOURCE: 'sr',
    SIGNED_START: 'st',
    SIGNED_EXPIRY: 'se',
    SIGNED_PERMISSIONS: 'sp',
    SIGNED_IDENTIFIER: 'si',
    SIGNATURE: 'sig',
    };
     
     
    var crypto = require('crypto');
    var util = require('util');
     
     
    //http://msdn.microsoft.com/en-us/library/windowsazure/hh508996.aspx
    var resource = 'https://%s.blob.core.windows.net/%s/%s%s';
     
     
    //Version of the storage rest API
    var signedVersion = '2012-02-12';
     
     
    //signedResource. use b for blob, c for container
    var signedResource = 'b'; //
     
     
    // The signedpermission portion of the string must include the permission designations in a fixed order that is specific to each resource type. Any combination of these permissions is acceptable, but the order of permission letters must match the order in the following table.
    var signedPermissions = 'rw'; //blob perms must be in this order rwd
     
     
    // Example - Use ISO 8061 format
    var signedStart = '';
    var signedExpiry = '';
     
     
    // Eample Blob
    // URL = https://myaccount.blob.core.windows.net/music/intro.mp3
    // canonicalizedresource = "/myaccount/music/intro.mp3"
    var canonicalizedResource = '/%s/%s/%s';
     
     
    //The string-to-sign is a unique string constructed from the fields that must be verified in order to authenticate the request. The signature is an HMAC computed over the string-to-sign and key using the SHA256 algorithm, and then encoded using Base64 encoding.
    var signature = '';
     
     
    //Optional. A unique value up to 64 characters in length that correlates to an access policy specified for the container, queue, or table.
    var signedIdentifier = '';
    view raw gistfile1.js hosted with ❤ by GitHub

    Uploading the Image directly to storage using the SAS

  5. To generate the sas we must insert a todoItem. which will now return the SAS property for the image. Thus update the OnTakePhotoClick handler to insert an item.
  6. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
    {
    //Take photo or video
    CameraCaptureUI cameraCapture = new CameraCaptureUI();
    StorageFile media = await cameraCapture.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
     
     
    //add todo item to trigger insert operation which returns item.SAS
    var todoItem = new TodoItem() { Text = "test image", ImageName = media.Name };
    await todoTable.InsertAsync(todoItem);
    items.Add(todoItem);
     
     
    //TODO: Upload image direct to blob storage using SAS
    }
    view raw gistfile1.cs hosted with ❤ by GitHub
  7. Update OnTakePhotoClick handler to update the image directly to blob storage using the HttpClient and the generated item.SAS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
{
//Take photo or video
CameraCaptureUI cameraCapture = new CameraCaptureUI();
StorageFile media = await cameraCapture.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
 
 
//add todo item
var todoItem = new TodoItem() { Text = "test image", ImageName = media.Name };
await todoTable.InsertAsync(todoItem);
items.Add(todoItem);
//Upload image with HttpClient to the blob service using the generated item.SAS
using (var client = new HttpClient())
{
//Get a stream of the media just captured
using (var fileStream = await media.OpenStreamForReadAsync())
{
var content = new StreamContent(fileStream);
content.Headers.Add("Content-Type", media.ContentType);
content.Headers.Add("x-ms-blob-type", "BlockBlob");
 
 
using (var uploadResponse = await client.PutAsync(new Uri(todoItem.SAS), content))
{
//TODO: any post processing
}
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

Run the application

  1. Hit F5 on the application and right click with your mouse to show the app bar
  2. Press the Take Photo button
  3. Observe that the SAS is returned from your Mobile Service
  4. Check your storage account now has the captured virtual High Five photo/video :)

Enjoy,
Nick

Building Connected Windows 8 Apps with Windows Azure

Hey – I thought I would share this video, deck and completed demo for all of you who attended my TechEd North America + Europe sessions

Are you building a connected Windows Metro style app? This session introduces you to Windows Azure and demonstrates how you can build connected experiences for your Windows 8 Metro style apps. After walking the through the fundamentals of both platforms, we take a deep dive as we demonstrate how you can use Windows Azure to support common geo-location, multimedia, data and push notification scenarios. At the end of this session, you will be empowered to begin building and deploying your own Windows 8 client applications that are powered by Windows Azure

You can download the full video in high res from channel 9 here

Download the deck Here
Download the source Here Note I have removed the connection strings for SQL + Windows Azure storage + Bing Maps. You will find all places that you need to replace these by doing a search for TODO-REPLACE. Enjoy!

Kind Regards,
Nick