Steve Spencer's Blog

The blog of Steve Spencer

Windows Store App Notifications, the Notification Hub and Background tasks

This article aims to talk about Windows Store Notifications and the Windows Azure Notifications Hub and it will attempt to collate the various articles in a single place to help you build notifications into your app.

In order for you to get an understanding of Windows notifications look at the following article

Introduction to Push Notifications - http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx. this provides a good overview of how push notifications work. To summarise the important bits.

1. Your store app needs to register with the Windows Notification Service to retrieve a unique URI for your instance of the app. Ideally you do this each time the app starts.

2. If the URI has changed then you need to notify your service that there is a new URI. Note: This URI expires every 30 days so your app needs to notify your service that this has been changed.

3. Your service sends notifications to this unique URI

You may have noticed above that I mentioned “Your service”. This is a critical piece of the notification mechanism and there are a number of ways to build this service. If you are not comfortable building backend services or you want something up and running quickly then mobile services might be the way to go for you. Here’s a tutorial that gets you started with mobile services http://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started/

If, like me, you already have a source of data and a service then you will probably want to wire in notifications into your existing service. depending upon how many devices you have using your app may dictate the method that you get the notifications onto the users device. there are a number of options:

  1. Local updates
  2. Push Notifications
  3. Periodic Notifications

Local updates require the creation of a background task that Windows runs periodically that calls into your data service, retrieves the data to put on the tiles and sends out tile notifications using the Windows Store app SDK

Updating live tiles from a background task - http://msdn.microsoft.com/en-us/library/windows/apps/jj991805.aspx. Provides a tutorial on building a background task for your Windows Store App. this tutorial is for timer tasks but it can easily be used for push notification tasks. The bits that are likely to change are the details of the run method, the task registration and the package manifest.

Two more important links that you will require when you are dealing with notifications:

Tile template catalogue http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx

Toast template catalogue http://msdn.microsoft.com/en-us/library/windows/apps/hh761494.aspx

These two catalogues are important as they provide you with details of the xml you need for each type of notifications

Push notifications are sent through the Windows Notification Service to your device.

You can send notifications to your device from your service by creating a notification and sending it to each of the devices registered to your service via the Windows Notification Service.

If you have a large number of devices running your app then you will probably want to use the Windows Azure Notification Hub. This is the simplest way to manage notifications to your application as the notification hub handles scaling, managing of the device registration and also iterating around each device to send the notifications out. The Notification hub will also allow you to send notifications to Windows Phone, Apple and Android devices. To get started with the notification hubs follow this tutorial:http://www.windowsazure.com/en-us/manage/services/notification-hubs/getting-started-windows-dotnet/

The nice feature of the notification hub is that is makes the code needed to send notifications simple.

 

NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString("<your notification hub connection string>", "<your hub name>");

 

var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">Hello from a .NET App!</text></binding></visual></toast>";

 

await hub.SendWindowsNativeNotificationAsync(toast);

Compare this to the code to send the notification without the hub:

 

byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);

 

 

HttpWebRequest request = HttpWebRequest.Create(uri) asHttpWebRequest;

request.Method =

"POST";

request.Headers.Add(

"X-WNS-Type", notificationType);

request.ContentType = contentType;

request.Headers.Add(

"Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

 

 

using (Stream requestStream = request.GetRequestStream())

requestStream.Write(contentInBytes, 0, contentInBytes.Length);

 

 

In addition you will need to retrieve the list of devices that are registered for push notifications and iterate around the list to send this to each device. You will also require a service that receives the registrations and stores them in a data store. You need to manage the scalability of these services. On the down side the notification hub is charged per message which means the more often you send notifications the greater the costs where as hosting a service is load based and the notifications will be sent out slower as the number of devices increases but this would generally be a lower cost. If you also take into account that you will need to send out notifications for each tile size and that will increase the activity count on the notification hub for each tile size (currently 3).

[Update: You can send out a single notification for all tile sizes rather than 3 separate notifications by adding a binding for each tile size in your xml see http://msdn.microsoft.com/en-us/library/windows/apps/hh465439.aspx for more details]

It is possible to send custom notifications to your app which can be received directly in the app or by using a background task. These are called Raw notifications. In order to receive raw notifications in a background task your app needs to be configured to display on the start screen. However Raw Notifications can be received in your app whilst it is running when it is not configured to display on the start screen. A Raw Notification is a block of data up to 5KB in size and can be anything you want.

The following code will send a raw notifications using the notifications hub:

 

string rawNotification = prepareRAWPayload();

 

Notification notification = new Microsoft.ServiceBus.Notifications.WindowsNotification(rawNotification);

notification.Headers.Add(

"X-WNS-Cache-Policy", "cache");

notification.Headers.Add(

"X-WNS-Type", "wns/raw");

notification.ContentType =

"application/octet-stream";

 

 

var outcome = await hub.SendNotificationAsync(notification);

In order to receive Raw Notifications in your app you need to add an event to the channel you retrieve from the Windows Notification Service:

 

var channel = awaitPushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();

 

channel.PushNotificationReceived += channel_PushNotificationReceived;

 

And then handle the notification received:

 

privatevoid channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)

{

 

switch (args.NotificationType)

{

 

    casePushNotificationType.Raw:

 

        ReceiveNotification(args.RawNotification.Content);

 

    break;

}

}

 

Note: the content of the notification is the block of data that you sent out.

Sample background task for Raw Notifications is here: http://msdn.microsoft.com/en-us/library/windows/apps/jj709906.aspx

Guidelines for Raw Notifications can be found here: http://msdn.microsoft.com/en-us/library/windows/apps/hh761463.aspx

Periodic notifications also require a service but the application periodically calls into a service to retrieve the tile notifications without needing to process the source data and then create the notifications locally. details about how to use periodic notifications can be found here: http://msdn.microsoft.com/en-US/library/windows/apps/jj150587

In summary Windows Store application notifications can be send to the app in a variety of ways and the mechanism you choose will depend upon how quick and how many notifications are required. Push notifications allow notifications to be sent whenever they are ready to send. Periodic and Local updates are pull notifications and require a service to be available to pull the data from. All of these will require some sort of service and all have an associated costs. The notifications hub is a useful tool to assist with notifications and it can be useful to manage the device connections as well as sending out notifications to multiple device type. It does however come at a cost and you need to work out whether it is a cost effective mechanism for your solution.

Gadgeteer, Signal R, WebAPI & Windows Azure

After a good night in Hereford at the Smart Devs User Group and my presentation at DDDNorth

Here are the links from my presentation and some from questions asked:

Gadgeteer: http://www.netmf.com/gadgeteer/

Signal-R: http://www.asp.net/signalr/

Web API: http://www.asp.net/web-api

The Signal-R chat example can be found at: http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr

Windows Azure Pricing Calculator : http://www.windowsazure.com/en-us/pricing/calculator/?scenario=full

Signal-R Scaleout using Service bus, SQL Server or Redis: http://www.asp.net/signalr/overview/performance-and-scaling/scaleout-in-signalr

The Windows Azure Training Kit: http://www.windowsazure.com/en-us/develop/net/other-resources/training-kit/

Gadgeteer Modules: http://proto-pic.co.uk/categories/development-boards/net.html

Fex Spider Starter Kit: http://proto-pic.co.uk/fez-spider-starter-kit/

 

In addition to these links I have more from my presentation at the DareDevs user group in Warrington

It is possible to drive a larger display from Gadgeteer using a VGA adapter. You use this the same way that the Display-T35 works using the SimpleGraphics interface for example.

VB eBook - Learn to Program with Visual Basic and Gadgeteer

Fez Cerberus Tinker Kit: https://www.ghielectronics.com/catalog/product/455 

Enabling Modern Apps

I’ve just finished presenting my talk on “Successfully Adopting the Cloud: TfGM Case Study”and there were a couple of questions that I said I would clarify.

1. What are the limits for the numbers of subscriptions per service bus topic. the answer is 2000. further details can be found at:http://msdn.microsoft.com/en-us/library/windowsazure/ee732538.aspx

2. what are the differences between Windows Azure SQL database and SQL Server 2012. The following pages provide the details:

Supported T-SQL: http://msdn.microsoft.com/en-us/library/ee336270.aspx

Partially supported T-SQL: http://msdn.microsoft.com/en-us/library/ee336267.aspx

Unsupported T-SQL: http://msdn.microsoft.com/en-us/library/ee336253.aspx

Guidelines and Limitations: http://msdn.microsoft.com/en-us/library/ff394102.aspx

3. Accessing the TfGM open data site requires you to register as a developer at: http://developer.tfgm.com

Thanks to everyone who attended I hope you found it useful.

Handling A Topic Dead Letter Queue in Windows Azure Service Bus

Whilst working on a project in which we we using the Topics on Windows Azure Service Bus, we noticed that our subscription queues (when viewed from the Windows Azure Management portal) didn’t seem to be empty even though our subscription queue processing code was working correctly. On closer inspection we found that our subscription queue was empty and the numbers in the management portal against the subscription were messages that had automatically faulted and had been moved into the Dead Letter queue.

The deadletter queue is a separate queue that allows messages that fail to be processed to be stored and analysed. The address of the deadletter queue is slightly different from your subscription queue and is the form:

YourTopic/Subscriptions/YourSubscription/ $DeadLetterQueue

for a subscription and

YourQueue/$DeadLetterQueue for a queue

Luckily you don’t have to remember this as there are helpful methods to retrieve the address for you:

SubscriptionClient.FormatDeadLetterPath(subscriptionClient.TopicPath, messagesSubscription.Name);

To create a subscription to the deadletter queue you need to append /$DeadLetterQueue to the subscription name when you create the subscription client

Once you have this address you can connect to the dead letter queue in the same way you would connect to the subscription queue. Once a deadletter brokered message is received the properties of the message should contain error information highlighting why it has failed. The message should also contain the message body from the original message. By default the subscription will move a faulty message to the dead letter queue after 10 attempts to deliver. You can also move the message yourself and put in sensible data in the properties if it fails to be processed by calling the DeadLetter method on the BrokeredMessage. The DeadLetter method allows you to pass in your own data to explain why the message has failed.

The DeadLetter can be deleted in the same was as a normal message by calling the Complete() method on the received dead letter message

Here is an example of retrieving a dead lettered message from a subscription queue

var baseAddress = Properties.Settings.Default.ServiceBusNamespace;
var issuerName = Properties.Settings.Default.ServiceBusUser;
var issuerKey = Properties.Settings.Default.ServiceBusKey;

Uri namespaceAddress = ServiceBusEnvironment.CreateServiceUri("sb", baseAddress, string.Empty);

this.namespaceManager = new NamespaceManager(namespaceAddress, 
                           TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerKey));
this.messagingFactory = MessagingFactory.Create(namespaceAddress, 
                           TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerKey));
var topic = this.namespaceManager.GetTopic(Properties.Settings.Default.TopicName);
if (topic != null)
{

    if (!namespaceManager.SubscriptionExists(topic.Path, 
                                  Properties.Settings.Default.SubscriptionName))
    {
        messagesSubscription = this.namespaceManager.CreateSubscription(topic.Path, 
                                            Properties.Settings.Default.SubscriptionName);
    }
    else
    {
        messagesSubscription = namespaceManager.GetSubscription(topic.Path, 
                                            Properties.Settings.Default.SubscriptionName);
    }
}
if (messagesSubscription != null)
{
    SubscriptionClient subscriptionClient = this.messagingFactory.CreateSubscriptionClient(
                                            messagesSubscription.TopicPath,
                                            messagesSubscription.Name, ReceiveMode.PeekLock);

   // Get the Dead Letter queue path for this subscription
    var dlQueueName = SubscriptionClient.FormatDeadLetterPath(subscriptionClient.TopicPath,
                                             messagesSubscription.Name);

   // Create a subscription client to the deadletter queue
    SubscriptionClient deadletterSubscriptionClient = messagingFactory.CreateSubscriptionClient(
                                           subscriptionClient.TopicPath, 
                                            messagesSubscription.Name + "/$DeadLetterQueue");

    // Get the dead letter message
    BrokeredMessage dl = deadletterSubscriptionClient.Receive(new TimeSpan(0, 0, 300));

   // get the properties
    StringBuilder sb = new StringBuilder();
    sb.AppendLine(string.Format("Enqueue Time {0}", dl.EnqueuedTimeUtc));
    foreach (var props in dl.Properties)
    {
        sb.AppendLine(string.Format("{0}:{1}", props.Key, props.Value));
    }
    dl.Complete();
}

MVP Cloud OS Community Week

Black Marble are participating in the Microsoft MVP Cloud OS Community Week. During the week commencing 9th September there will be daily events held at Cardinal Place, Victoria, London. Richard and I along with other MVPs will be participating in the event on Friday 13th Sept which is titled “Enables Modern Business Applications”. The sessions will include developing services for modern apps, case studies, ALM and much more. Further details and registration can be found at: http://mvpcloudosweek-eorg.eventbrite.co.uk/.

Registration for this specific day can be found at: http://enablemodernapps-es2.eventbrite.co.uk/?rank=1

Pricing Changes to Windows Azure

Scott Guthrie made an announcement on his blog about changes to the way Windows Azure is priced

http://weblogs.asp.net/scottgu/archive/2013/06/03/windows-azure-announcing-major-improvements-for-dev-test-in-the-cloud.aspx

The main two changes that will affect most people are

  1. Per minute Billing
  2. No charge for turned off VMs

Prior to this announcement you would be charge for Windows Azure usage in hour blocks of time which meant that if you used 5 minutes of compute time or 55 minutes of compute time you were charged for the full hour, similarly if you used 1 hour 5 minutes you were charged for 2 hours. This change now means that you will be charged for 5 minutes, 55 minutes and 1 hour 5 minutes, matching your actual usage, This doesn’t affect you if you have a fixed usage but for those who take advantage of the easy scalability of Windows Azure this could have a significant impact on your costs.

By far the biggest cost saving is the ability to turn off a VM and not be charged for its usage. Prior to this change you would need to undeploy the solution in order to not be charged and just turning it off would still incur charges, This allows for systems that are in staging, dev/test scenarios, training systems etc to be left deployed and configured but turned off without being charged. Saving both time and money. I have a number of customers where this change alone should half their monthly bills as they have systems running that are not needed all the time but can not be undeployed because of the time taken to deploy and configure them. The ability to turn off VMs will provide both customers and developers with flexibility whilst reducing costs. Always a good thing.

Windows Azure and SignalR with Gadgeteer

I’ve been playing with Gadgeteer (http://www.netmf.com/gadgeteer/) for a while now and I am a big fan of the simple way we can build embedded hardware applications with high functionality. We have a proof of concept device that includes a Colour touch screen, RFID reader and an Ethernet connections. This device is capable of connecting to a web api REST service which we have hosted in Windows Azure and we can use this service to retrieve data from our service depending upon the RFID code that is read. This works well but there are times when we would like to notify the device when something has changed. SignalR seems to be the right technology for this as it removes the need to write polling code in your application.

Gadgeteer uses the .Net Micro framework which is a cut down .Net framework and doesn’t support the ASP.NET SignalR libraries. As we can use web api using the micro framework using the WebRequest classes,  I wondered what was involved to get SignalR working on my Gadgeteer device.

The first problem was to work out the protocol used by SignalR and after a short while trawling the web for details of the protocol I gave up and got my old friend fiddler out to see what was really happening.

After creating a SignalR service I connected my working example to the signalR hub running on my local IIS..

The first thing that pleased me was that the protocol looked fairly simple. It starts with a negotiate which is used to return a token which is needed for the actual connection.

GET /signalr/negotiate?_=1369908593886

Which returns some JSON:

{"Url":"/signalr","ConnectionToken":"xyxljdMWO9CZbAfoGRLxNu54GLHm7YBaSe5Ctv6RseIJpQPRJIquHQKF4heV4B_C2PbVab7OA2_8KA-AoowOEeWCqKljKr4pNSxuyxI0tLIZXqTFpeO7OrZJ4KSx12a30","ConnectionId":"9dbc33c2-0d5e-458f-9ca6-68e3f8ff423e","KeepAliveTimeout":20.0,"DisconnectTimeout":30.0,"TryWebSockets":true,"WebSocketServerUrl":null,"ProtocolVersion":"1.2"}

I used this JSON to pull out the connection id and connection token. This was the first tricky part with the .Net Micro framework. There is not the same support for JSON serialisation you get with the full framework plus the string functions are limited as well. For this I used basic string functions using Substring and IndexOf as follows:

int index = negJson.IndexOf("\""+token+"\":\"");
if (index != -1)
{
    // Extracts the exact JSON value for then name represented by token
    int startindex = index + token.Length + 4;
    int endindex = negJson.IndexOf("\"", startindex);
    if (endindex != -1)
    {
        int length = endindex - startindex;
        stringToExtract = negJson.Substring(startindex, length);
    }
}

With the correct token received Fiddler led me to the actual connection of signalR:

GET /signalr/connect?transport=webSockets&connectionToken=yourtoken&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=2 HTTP/1.1

Looking at this I could determine that I needed to pass in the token I retrieved from negotiate, the transport type and the name of the hub I want to connect to. After a bit of investigating I used the transport of longPolling.

Now as I think I understood the protocol, I tried to implement it in SignalR. The first issue that arose was what to send with the negotiate call. I figured that this was some sort of id of the client that is trying to connect so I decided to use the current tick count. This seemed to work and I guess that as long as my devices don’t connect at exactly the same time then Signal R would work. I’ve had no problems so far with this.

Upon connecting to the hub I needed to create a separate thread to handle signalR so that the main device wouldn't stop running whilst the connection to the SignalR hub was waiting for a response. Once a response is received the response returns with a block of JSON data appropriate to the SignalR message being received. This needs to be decoded and passed onto the application. You then need to reconnect back to the SignalR hub. The period between receiving data and then reconnecting back to the hub needs to be small. Whilst the message is being processed it cannot receive any more message and may miss some data. I retrieve the response stream and then pass the processing of the stream to a separate thread so that I can reconnect to the hub as fast as possible.

This is not a full implementation of SignalR on the .Net Micro-framework but it is the implementation of a simple client and can be used fairly successfully on the Gadgeteer device. I still need to do a little more work to try to speed up the connections as it is possible to miss some data.

The SignalR hub is hosted on a Windows Azure website along side the web api service which allows both web, Windows 8 and Gadgeteer applications to work side by side.

Gadgeteer has opened up another avenue for development and helps us to provide more variety of devices in a solution

Global Windows Azure Bootcamp

The Global Windows Azure Bootcamp is a one day deep dive session to get you developing on Windows Azure. This is a global event organised by the community for the community. There will be a number of events held at locations across the globe. This event will happen on April 27th, 2013 and Black Marble will be hosting one of the UK events at our offices near Bradford.

Join me and my fellow MVPs Robert Hogg and Andy Westgarth and sign up here to attend this event at Black Marble.

For further information visit the the Global Windows Azure Bootcamp website

Imagine Cup NE Hackathon

We’ve just come back from the Imagine Cup NE hackathon in Newcastle. We had a great time with all the students from Universities and Colleges around the NE of England. Rik has written a good blog post about it. As always I am impressed by the young talent there and there was a number of good ideas. This year the Imagine Cup world finals are being held in St. Petersburg in Russia with three main competitions:

  1. Games
  2. Innovation
  3. World Citizenship

There were entries in all three categories. The two day hack consisted of a series of talk/presentations from MVPs and other industry experts who also provided support and guidance for the teams throughout the 2 days.

At the end of the two days the teams had 10 minutes to present their ideas and be “grilled” in a Q & A session. All teams equipped themselves well.

Helping out with the Imagine Cup not only helps the new generation of software developer, it also inspires us to be better at what we do. There’s some good young talent that are going to give us a good run for our money in a few years time. We’d better be ready for them Smile

Gadgeteer, Ethernet and Windows Azure

I was having problems getting my Gadgeteer ethernet card initialised and running. I wanted to set it up to use DHCP but I never got an IP address assigned. I am using a GHI Electronics J11D ethernet card and browsing for examples seemed to pull up a lot of code but none of it seemed to work or the code didn’t seem to match what the libraries were providing. I eventually found the solution.

// Wire up the event handler to notify when the ip address has been assigned 
// and the port is ready to use
ethernet_J11D.Interface.NetworkAddressChanged += new
   NetworkInterfaceExtension.NetworkAddressChangedEventHandler(
Interface_NetworkAddressChanged); // Open the ethernet port ethernet_J11D.Interface.Open(); // Assign the network stack to the ethernet card if (!ethernet_J11D.Interface.IsActivated) { NetworkInterfaceExtension.AssignNetworkingStackTo(ethernet_J11D.Interface); } // Turn on DHCP and Dynamic DNS ethernet_J11D.Interface.NetworkInterface.EnableDhcp(); ethernet_J11D.Interface.NetworkInterface.EnableDynamicDns();

It was the line (NetworkInterfaceExtension.AssignNetworkingStackTo(ethernet_J11D.Interface); ) that was the issue, once that was in everything worked fine.

I can now connect to my Windows Azure Websites hosted web api/signalR service.

The code for this is fairly standard and once I got the connection it worked well. The code below shows you how to call the web api service from Gadgeteer. This method works for both GET (read) and PUT (update) requests.

private string CallWebservice(string fn, bool put, string data)
{

string responseFromServer ;
try
{
    // Create a request for the URL. 
    WebRequest request = WebRequest.Create(url + fn);

    // set a timeout of a nice big value - 10 minutes
    request.Timeout = 600000;
    if (put)
    {
        request.Method = "PUT";
        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
        byte[] arr = encoding.GetBytes(data);
        request.ContentType = "application/json";
        request.ContentLength = arr.Length;
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(arr, 0, arr.Length);
        requestStream.Close(); 

    }

    // Get the response.
    WebResponse response = request.GetResponse();

    // Get the stream containing content returned by the server.
    Stream dataStream = response.GetResponseStream();

    // Open the stream using a StreamReader for easy access.
    StreamReader reader = new StreamReader(dataStream);

    // Read the content.
    responseFromServer = reader.ReadToEnd();

    // Tidy up
    reader.Close();
    response.Close();
}
catch (Exception ex)
{
    Debug.Print(ex.Message);
}

return responseFromServer ;
}