Category: Azure Notification Hub

Azure Notification Hub – Double Message Gotcha

I recently worked on a piece of Azure hosted software that was required to send a large volume of push notifications to mobile devices and so decided to give Azure Notification Hubs a whirl.

On the whole I found it to be pretty easy to set up and get going with and very well documented with walkthroughs for most scenarios (both server side and device) across all the major platforms.

But, and you knew there was a but coming didn’t you?, I did come across one major gotcha while building an implementation based off the tutorial on sending notifications from your server.

After implementing this and doing a bit of debugging I was finding that every time I sent a message from the server to the device my device was responding to it multiple times. Due to how devices and the registration process work you do have to be careful to ensure that your device isn’t already registered with the notification hub and Microsoft themselves show you how to do this in this code snippet:

public class DeviceRegistration
{
    public string Platform { get; set; }
    public string Handle { get; set; }
    public string[] Tags { get; set; }
}
 
// POST api/register
// This creates a registration id
public async Task<string> Post(string handle = null)
{
    string newRegistrationId = null;
 
    // make sure there are no existing registrations for this push handle (used for iOS and Android)
    if (handle != null)
    {
        var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100);
 
        foreach (RegistrationDescription registration in registrations)
        {
            if (newRegistrationId == null)
            {
                newRegistrationId = registration.RegistrationId;
            }
            else
            {
                await hub.DeleteRegistrationAsync(registration);
            }
        }
    }
 
    if (newRegistrationId == null) 
        newRegistrationId = await hub.CreateRegistrationIdAsync();
 
    return newRegistrationId;
}
 
// PUT api/register/5
// This creates or updates a registration (with provided channelURI) at the specified id
public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate)
{
    RegistrationDescription registration = null;
    switch (deviceUpdate.Platform)
    {
        case "mpns":
            registration = new MpnsRegistrationDescription(deviceUpdate.Handle);
            break;
        case "wns":
            registration = new WindowsRegistrationDescription(deviceUpdate.Handle);
            break;
        case "apns":
            registration = new AppleRegistrationDescription(deviceUpdate.Handle);
            break;
        case "gcm":
            registration = new GcmRegistrationDescription(deviceUpdate.Handle);
            break;
        default:
            throw new HttpResponseException(HttpStatusCode.BadRequest);
    }
 
    registration.RegistrationId = id;
    var username = HttpContext.Current.User.Identity.Name;
 
    // add check if user is allowed to add these tags
    registration.Tags = new HashSet<string>(deviceUpdate.Tags);
    registration.Tags.Add("username:" + username);
 
    try
    {
        await hub.CreateOrUpdateRegistrationAsync(registration);
    }
    catch (MessagingException e)
    {
        ReturnGoneIfHubResponseIsGone(e);
    }
 
    return Request.CreateResponse(HttpStatusCode.OK);
}

You’ll notice the comment in the built of the Post action about making sure their are no existing registrations for the push handle. The handle is a token you obtain from the device and use as illustrated as part of the registration process.

The problem is – this code sample doesn’t work.

I learned the hard way that when the registration is created (in the Put action) the notification hub converts the handle to all upper case text. The handle from my device (which I obtained using the Cordova PushPlugin – I was working in Ionic) contained a mix of lower case letters and numbers.

When you subsequently search for registrations that match the handle (var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100)) it performs a case sensitive search and none of your previous registrations will be found.

The result is that you can find yourself registering the same device token multiple times against different registration IDs and when you do a message send it is sent multiple times – multiple registrations == multiple sends.

If you suspect you might have a similar problem you can enumerate all registrations with the GetAllRegistrationsAsync method on the NotificationHubClient.

Other than that, and as I said earlier, my experience with the Notification Hub was really very smooth.

Contact

  • If you're looking for help with C#, .NET, Azure, Architecture, or would simply value an independent opinion then please get in touch here or over on Twitter.

Recent Posts

Recent Tweets

Invalid or expired token.

Recent Comments

Archives

Categories

Meta

GiottoPress by Enrique Chavez