Azure Event Hubs from WinRT/UWP Apps

Just a small thing that caught me out the other day. I wanted to send some simple data from a Windows 10 UWP app to an event hub in Azure.

There’s a great guide to getting started with event hubs here;

Getting Started with Event Hubs

which worked really well for me up until the section ‘Send messages to Event Hubs’ which has a step 3 which asks you to install the NuGet package WindowsAzure.ServiceBus.

Now, in the tutorial I think that’s all fine because it’s a console application that’s being built on top of .NET Framework.

However, Windows Store/Phone apps and UWP apps are all on .NET Core, not .NET Framework and when I try and install that NuGet package I get;

image

which seems to be saying that the package Microsoft.WindowsAzure.ConfigurationManager isn’t compatible with .NET Core.

I did a bit of a web search and came across a bug report on this;

Microsoft.WindowsAzure.ConfigurationManager doesn’t support Windows 8.1

and it looks like this has been closed off as ‘by design’ so I’m not sure at the time of writing what the recommended way of using event hubs from a Windows Store or UWP app is meant to be.

Naturally, a UWP app might be running on an IoT device like a Raspberry Pi 2 powered by Windows 10 for IoT Core which would be a scenario where you may well want to use an event hub for gathering data so I was a bit disappointed not to be able to use this package because it contains the EventHubClient class which makes it pretty easy to publish data to an event hub but I asked around a little and ended up using the package ampqnetlite instead and switching to AMQP protocol to get the data to my event hub.

So…just a note if you find yourself in the same situation and I’ll update the post if I find that there’s a way of getting that EventHubClient class to be a part of a UWP app, it’s possible that it’s just an awareness thing on my part.

Windows/Phone 8.1–Running Code in Response to Cloud Push Notifications

One of the features of Windows 8.0/8.1 apps is the ability to respond to a raw push notification delivered from the Windows Notification Service in the cloud.

You can read about raw push notifications on the developer centre (I dug out the link – http://msdn.microsoft.com/en-us/library/windows/apps/jj676791.aspx – to save you having to search around).

A raw notification is just a string up to around 5KB of data in size. When an app receives a raw notification, I think it can do one of two things;

  1. If the app was lucky enough to be actually running then it can register an event handler to receive the data from a raw notification as it hits the device.
  2. The app can register a background task which will run on receipt of the raw notification.

Of the two I think it’s fair to say that (2) is the only pragmatic approach unless you want some kind of UI like this in your app Winking smile

image

that second option though is a powerful thing – it effectively means that code running in the cloud can trigger the execution of code on a device.

That code running on the device might do something “quiet” like writing the received data into a file or it might take an active step like executing some web request to get new data from the cloud and it might combine this with something a bit more “invasive” like popping up a toast message to tell the user that something has happened.

I drew out an example scenario at one point that looked as below;

image

The idea here is that there’s a football app on the phone which has registered a background task to receive raw push notifications. In the cloud there’s some football service which is monitoring a game and sending raw push notifications to the app whenever there’s a goal scored in the game.

The app on the device can then choose (maybe based on a setting) to simply record the details of all of these goals in storage until the game ends and then (perhaps) notify the user that the game is over and their team won/lost having quietly recorded the details of 4 raw push notifications (goals) in the meantime;

image

What does it take to get this sort of thing up and running?

“Not too much” – here’s a quick step by step way of getting this working. There are perhaps 4 main steps if using Windows Azure;

  1. Creating a notification hub.
  2. Creating an app, associating it with the Store and configuring the notification hub to talk to WNS for it.
  3. Executing code on the client-side to register with that hub.
  4. Writing a background task to execute on receipt of a raw push notification and writing code to register that background task.
  5. Writing server-side logic to send raw notifications when something “interesting/relevant” to the user happens.

I’m going to miss out step 5 here but I thought I’d run through 1-4. It’s worth saying that Azure Mobile Services has ways of making this easier but I’ll work here without Mobile Services just for novelty Smile

Step 1 – Creating a Notification Hub

I can use the Azure Portal to create a notification hub;

image

and now I’ve got a hub called “mtaultyHub”. What I’m going to need from this hub are two things;

  1. I need to configure the hub to be able to speak to the Windows Notification Service in the cloud and to do that I’m going to need an app..
  2. I need to be able to configure the app to speak to the hub and to do that I’m going to need a connection string for the hub.

Step 2 I can gather from the hub’s dashboard page;

image

which launches up a dialog;

image

where I can copy out the connection string highlighted – I’ll need this in a moment.

Step 2- Create a New App, Associate with Store & Grab Identifiers

On the client side, I can make a new, blank Windows Phone 8.1 app in Visual Studio 2013 Update 2 RC and then I can associate it with the Windows Phone Store via the Visual Studio menu;

image

and that pops up a dialog where I can make a new app name or re-use an existing one;

image

and once the association is made I can navigate to http://dev.windowsphone.com and then to Dashboard;

image

and that leads to Apps and including my “Not Started” apps;

image

and if I navigate into that mtaultyTestHub app I have to get past the initial question;

image

and then I can scroll right to the bottom of that page and find this link;

image

and that gets me to this page;

image

and I can take the Package SID and the Client Secret and I can copy them across to the configuration page for my notification hub;

image

and that’s then configured the hub to be able to talk to WNS.

Step 3 – Run Client Side Code to Register with Notification Hub

I can then write some code in my phone app to obtain a push notification channel URI – e.g;

 private async void OnRegister(object sender, RoutedEventArgs e)
    {
      var channel = 
        await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
      
    }

and that gets me a channel (with a URI) for the app for the user on the device and I also need to send the URI to the notificaton hub to register this client as a possible recipient of push notifications. One way to do that is to add client-side SDK classes for Azure Notification Hubs from Nuget for which I used;

Install-Package WindowsAzure.Messaging.Managed

in the Nuget console. With that in place I can then expand out that previous code;

    private async void OnRegister(object sender, RoutedEventArgs e)
    {
      var channel = 
        await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();

      NotificationHub hub = new NotificationHub(
        "mtaultyhub",
        "Endpoint=sb://mtaultyhub-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=notIncluded");

      await hub.RegisterNativeAsync(channel.Uri, new string[] { "Group1", "MikeTaulty" });
    }

and then if I run this code, I have this particular client registered for push notifications from the hub. If I switch on “Toast Notifications” in my app’s manifest;

image

then I could use Visual Studio to send a quick test toast notification to see if things have registered correctly;

image

which raises this page in Visual Studio;

image

and pressing the “Send” button talks to the cloud which talks to the device which pops this toast in response (I’m doing this in the emulator);

image

and if I stop broadcasting and use a made-up tag like “Foo” then nothing happens down on the device;

image

whereas if I pass one of the tags that I associated with the registration;

image

then I see the toast down on the device and so I can feel comfy that things are working ok at least from the point of view of a toast notification but what about a raw notification activating a background task?

Step 3 – Writing a Background Task to Execute on Receipt of a Raw Push Notification

I need to write a background task – it’s important to make sure that you’re writing a Windows Runtime Component here rather than a .NET class library because background tasks need to be implemented as Windows Runtime Components.

I can add a project to my solution;

image

and then do a quick implementation of a background task which will just dump the received data out to the debugger;

namespace WindowsRuntimeComponent1
{
    public sealed class MyTask : IBackgroundTask
    {
      public void Run(IBackgroundTaskInstance taskInstance)
      {
        RawNotification rawNotification = taskInstance.TriggerDetails as RawNotification;

        if (rawNotification != null)
        {
          Debug.WriteLine(
            string.Format("Received from cloud: [{0}]",
            rawNotification.Content));
        }
      }
    }
}

and I can reference that project from my main app project and write a little code to register the background task;

      await BackgroundExecutionManager.RequestAccessAsync();

      // Get rid of existing registrations.
      foreach (var task in BackgroundTaskRegistration.AllTasks)
      {
        try
        {
          task.Value.Unregister(false);
        }
        catch // hack
        {
        }
      }
      BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
      builder.Name = "Push Task";
      builder.TaskEntryPoint = typeof(WindowsRuntimeComponent1.MyTask).FullName;
      builder.SetTrigger(new PushNotificationTrigger());
      builder.Register(); 

and update my manifest to make sure that this registration is going to be allowed;

image

and then I can run that code to get the background task register and then use the test page in Visual Studio to send a raw notification to the device;

image

and I see the debugger output;

image

and that all works quite nicely – we have the cloud able to deliver string data down to the device and the device able to respond to that notification by executing code which can pick up the payload sent as part of the push notification.

“All” that’s left is to come up with a proper scenario and a cloud-based service to run logic and deliver notifications as/when something of relevance to a user (or group of users) happens. Again, Azure Mobile Services can help in terms of implementing that cloud service and its logic.

I think this is a very powerful new capability for Windows Phone 8.1 development – the device able to pick up almost “real time” notifications from the cloud and act upon them.

Azure Mobile Services Update–Custom APIs

Three weeks ago, Scott Guthrie posted about updates to Azure Mobile Services – I’ve written a little about Mobile Services here in the past and which I’ve also demo’d at various conferences, user groups and so on around the UK (and beyond). Then just last week at Build, the second day keynote announced that Mobile Services had come out of its preview phase and was now a fully “released” product ready to go.

I thought it was about time that I tried to catch up with Scott’s post. Of course, you’ll get the definitive view from reading what Scott wrote or from going on over to the Windows Azure site and looking at the quick-starts, samples or reference documentation.

There are a lot of changes to Mobile Services detailed in Scott’s post but the main thing that interested me was the new support for custom APIs. In talking about Mobile Services (and in writing about it) I’ve encountered many people who are enthused by what the service provides but who questioned whether the previous capabilities of;

  • Create a table.
  • Associate scripts for read/insert/update/delete.

(along with creating scripts that could be run on a schedule or on demand)

were enough for their needs. The questions I’d get were generally along the lines of how Mobile Services would support scenarios where you wanted to provide services that aren’t directly associated with a single table and before these recent updates you’d either not be able to do these things or you’d perhaps struggle to try and shoe-horn this functionality into a script associated with a table where it didn’t perhaps fit.

With that in mind, I thought I’d experiment a little with custom APIs. One of the things about “going custom” is that it exposes me to more of node.js which I don’t really know very much about at all but I did notice a key line in Scott’s post;

“We will also be adding support for custom APIs written using .NET in the future as well.”

Which is something else I’ve heard from UK developers around Azure Mobile Services so it’s cool to know that .NET is on its way Smile

I figured that I’d try a simplified customer/address kind of scenario and see how I got on in exposing a join across those tables from a service and so I wandered up to the azure management portal, created a new service called mtJoinTest and got hit with one of the changes that Scott talked about – a free 20MB SQL database. Nice to see;

image

I created a quick Customer table and an Address table in the mobile service and then went to SQL Management Studio and gave those tables a small, simple schema and added (via Management Studio, not via Mobile Services) a CustomerAddresses table;

image

That means that mobile services is happy to provide automatically generated (and scriptable) RESTful services to do CRUD for my Customer table and my Address table and they show up in the UI on the portal;

image

and I can get data from the table using (in this case) Fiddler to cruft up a quick HTTP GET to my Customer table’s JSON endpoint;

image

but I can’t get to CustomerAddresses because there’s no table for that surfaced into Mobile Services – I never told Mobile Services about that table and;

  1. I don’t actually want direct access to that table.
  2. I may not want to make that table fit with the requirements that Mobile Services has for a table (e.g. a primary key column of type bigint named id).

Attempting to hit the table with Fiddler reassures me that it’s not quietly been made available;

image

That’s excellent because I want to write my own custom service to join those two tables here and I can wander into the new “API” section of the Mobile Services management portal to do just that;

image

which raises this dialog;

image

which I found interesting from the point of view of offering both “PUT” and “PATCH”. I’ve said many times before that I’d never encountered “PATCH” until I started sniffing traffic from Mobile Services and saw that it was being used for updates rather than “PUT” so it’s interesting to see them both side by side and I’ll admit that I’m not so sure whether I’d ever have different handling for those 2 verbs.

As an aside, I believe PUT is intended to replace a whole entity whereas PATCH is intended to update bits of it but I’m not going to worry about that here.

I can then go and set about trying to edit the script behind those verbs;

image

and “GET” seemed like the place to start and so I had a bit of a stab at joining my tables together and allowing for the possibility that the user of the service may want to query for all customer/address combinations or they might want to find out which customers live at a particular address or which addresses are associated with a particular customer. Here’s my first attempt;

exports.get = function(request, response)
{       
    if (request.query.customerId && request.query.addressId)
    {
        response.send(statusCodes.BAD_REQUEST);
    }
    else
    {    
        var sql = 
            'select c.Id cId, c.firstName, c.lastName, c.email, ' + 
            'a.Id aId, a.houseNameNumber, a.streetName, a.postCode ' +
            'from mtJoinTest.Customer c ' +
            'inner join mtJoinTest.CustomerAddresses ca ' +
            'on c.id = ca.customerId ' +
            'inner join mtJoinTest.address a ' +
            'on a.id = ca.addressId';
        
        var params = [];
    
        if (request.query.customerId)
        {
            sql += ' where c.id = ?';    
            params.push(request.query.customerId);
        }
        if (request.query.addressId)
        {
            sql += ' where a.id= ?';
            params.push(request.query.addressId);
        }
        
        request.service.mssql.query(sql, params,
            {
                success: function(results)
                {
                    response.json(statusCodes.OK, results);
                },
                error : function()
                {
                    response.send(statusCodes.INTERNAL_SERVER_ERROR);
                }
            }
        );
    }
}

and that seems to work ‘reasonably well’ in my not-so-extensive testing from Fiddler, making a few requests and having a look at a few responses;

image

image

image

A Quick Word on URIs

In the example above I’ve ended up using URIs like /customeraddress?addressId=1 where the query string is being used to pass the identifier of the (optional) address or customer ID qualifier. I might have wanted to use a scheme like /customeraddress/address/1 or perhaps /customeraddress/customer/1 or something along those lines but as far as I can tell at the time of writing that’s not something that I can do via a custom API – that is, I think if I define an API called foo then I’m not sure that I can have any URI with additional path segments beyond /foo handled by my service.

I’ll update the post if I find out that I can.

If I wanted to flesh this out a little with a delete and an insert operation then I can do that. I’m not sure whether it makes sense to offer an “update” operation because if customer C is living at address A and they then move to address B then it possibly makes sense to delete the original customer address record and insert a new one especially given that it’s possible that the customer might reside at both address A and address B for a little while. So…I didn’t write update but I made an attempt to write delete;

exports['delete'] = function(request, response)
{
    if ((!request.query.id) || (Object.keys(request.query).length > 1))
    {
        response.send(statusCodes.BAD_REQUEST);
    }
    else
    {
        var sql = 'delete mtJoinTest.CustomerAddresses where id=?';
        
        request.service.mssql.query(sql, [request.query.id],
            {
                success: function()
                {
                    // think a 204 is the right response.
                    response.send(204);
                },
                error: function()
                {
                    // bit of an assumption.
                    response.send(statusCodes.NOT_FOUND);
                }
            }
        );
    }
}

and I attempted to allow post;

exports.post = function(request, response)
{    
    var sql = 
     'insert mtJoinTest.CustomerAddresses(customerId,addressId) values(?,?);' +
     'select @@identity as id';
    
    // It took me longer than I would expect to get this call to mssql.query to work because
    // I failed to understand that it calls your success handler for each resultset
    // from the DB (I have two).
    var firstTime = true;
    
    request.service.mssql.query(sql, [request.body.customerId, request.body.addressId],
        {
            success: function(results)
            {                         
                if (!firstTime)
                {
                    // this is not very nice, I need a better way to deal with URIs
                    // to be more like a RESTful service.
                    response.location('?id=' + results[0].id);
                    response.send(201);
                }          
                firstTime = !firstTime;           
            }
        }
    );
}

I must admit that I spent over an hour trying to write that post method and the simple reason for that was that I’m new to using mssql and I didn’t understand that the success handler that I passed to it is called multiple times – once for each resultset that SQL is sending back so in my case my SQL statements cause it to be called twice which I hadn’t expected and I spent a long time before I asked somebody and, thankfully, Josh told me how it worked Smile

With those two additional verbs in place I can invoke my service (from Fiddler in this case) in order to delete an entry in my customeraddresses table;

image

or to insert an entry and tie up a customer to an address;

image

although I’d admit that I changed the code slightly from what I pasted above to try and do a bit of a better job on the location header that I’m sending back.

Consuming Custom APIs on the Client

Of course, the client for these kinds of services isn’t always going to be Fiddler Smile so I thought I’d take a look at what the Mobile Services guys had done with their client stack to make it “easy” to consume these custom APIs.

I spun up a new Windows 8 blank project (in .NET), added in the Mobile Services bits from NuGet and it seemed pretty discoverable to me that the MobileServiceClient (as doc’d here) has grown a new couple of methods called InvokeApiAsync.

If you’ve looked at the client-side APIs in .NET before then you’d know that they follow a pattern of offering a strongly typed variant which relies on data-contract serialization and a JSON variant where you pass in/out JSON objects.

These APIs seem to follow a similar model. For instance, I can invoke my GET API with something like;

      IMobileServiceClient client = new MobileServiceClient(
        "http://mtJoinTest.azure-mobile.net/");

      JToken token = await client.InvokeApiAsync("customeraddress", HttpMethod.Get,
        new Dictionary<string, string>()
        {
          { "customerId", "1" }
        }
      );

and then work with the JSON object that I get back ( the framework makes use of JSON.NET as it did in previous versions ) or I can do some “strong typing” as in;

      IMobileServiceClient client = new MobileServiceClient(
        "http://mtJoinTest.azure-mobile.net/");

      var addresses = await client.InvokeApiAsync<IEnumerable<CustomerAddress>>(
        "customeraddress",
        HttpMethod.Get,
        new Dictionary<string, string>()
        {
          { "customerId", "1" }
        }
      );

and, of course, that needs a CustomerAddress class to work with which I defined as;

  [DataContract(Name = "customeraddress")]
  public class CustomerAddress
  {
    [DataMember(Name = "cId")]
    public int CustomerId { get; set; }
    [DataMember(Name = "firstName")]
    public string FirstName { get; set; }
    [DataMember(Name = "lastName")]
    public string LastName { get; set; }
    [DataMember(Name = "email")]
    public string Email { get; set; }
    [DataMember(Name = "aId")]
    public int AddressId { get; set; }
    [DataMember(Name = "houseNameNumber")]
    public string HouseNameNumber { get; set; }
    [DataMember(Name = "streetName")]
    public string StreetName { get; set; }
    [DataMember(Name = "postCode")]
    public string PostCode { get; set; }
  }

What surprised me a little was that I could magically use IEnumerable<CustomerAddress> as the generic parameter type to that call to InvokeApiAsync and something in the framework figured out how to do the right thing and give me back a List<T> from the results of de-serialization. I was impressed by that Smile

That all seems fairly simple and understandable and, over-all, it opens up Mobile Services to be more broadly applicable for server-side scenarios that need more than just CRUD operations against a table – very nice to see this custom API feature come to fruition.