Month: August 2015

AccidentalFish.ApplicationSupport v2.0.0

As part of my documentation push I’m also dealing with some unresolved naming issues and inconsistencies I’ve noticed since releasing v1.0.0.

As addressing some of this means breaking changes, and following the semver rules, I’ll be releasing this as v2.0.0 of the framework in due course.

I’m tracking the changes in a release note as I make them and you can already see that here if you want a view of what is coming.

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.

AccidentalFish Application Support Updates

A quick post with a few bits of news regarding my lightweight application framework.

Logger

Yesterday I pushed out a new version of the packages that contain an updated logger that will work alongside my Owin middleware for HTTP logging and correlation ID attachment.

If you use that middleware package, and an appropriate filter (Web API or MVC) in a project using the logger then everything should just work.

Versioning

I’ve not been strict enough over the versioning of this framework and I’m going to tighten this up by adopting the Semver format and guidelines. I am aware of a few, minor, upcoming breaking changes as I’ve realised I’ve got some naming inconsistencies in the interfaces (particularly around the use of async) – at least by adopting Semver it will be clear when I make those changes.

Documentation

The long promised documentation is now underway – something of a minor miracle as I’m always distracted by Visual Studio! I’m hosting it on GitHub Pages, go check it out. It’s early days but I’m hoping to make fairly short work of getting started guides so at least there’s a clear way into the framework.

I’m writing the documentation using Markdown and that’s getting translated into HTML on GitHub Pages via Jekyll. I’ve not used Jekyll before but it’s pretty simple to get going with and coupled with Markdown seems to be a neat solution to creating verbose documentation. I’ll be producing API reference documentation using C#s XML comments and Sandcastle.

Http Logging and Correlation IDs

I’ve recently pushed out some new open source for HTTP logging / tracing and alongside that support for adding correlation IDs to http calls and tracking them across MVC and Web API applications.

It’s fully documented and can be found in GitHub and on NuGet. The logger is independent of storage mechanism however I’ve currently only created a repository for Azure. I’ll probably add a SQL repository shortly.

The NuGet packages are entirely free standing other than the minimal Microsoft dependencies required.

I’m currently working on adding correlation ID support to the logging framework contained within the wider AccidentalFish.ApplicationSupport framework and I expect that to roll out early next week.

Alongside this I’m having a bit of a documentation push for all my open source. Other than Markdown and Sandcastle I’d be very interested in hearing how others have approached creating large amounts of technical documentation in the Microsoft space.

As ever feedback and issue reports are very welcome.

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