Monday, April 13, 2015

Get CRM on Your Microsoft Band Using Azure and Xamarin

The goal of this exercise is to get a user specific notification based on an event in Dynamics CRM onto my Microsoft Band in its own specific CRM tile. The approach I ended up taking contains quite of bit of “configuration” as opposed to writing actual code. In fact had I opted not to make the notifications coming from CRM targeted to specific users the code would have ended up being substantially less but at the same time would have been less useful in a real world scenario.

Approach


The general flow starts off using the native CRM to Azure integration to push data into an Azure Service Bus Queue. From there an Azure Mobile Services job reads from the queue and sends a push notification via an Azure Notification Hub. The push notification is then accepted by a device listening for the user specific message through a mobile application written using C# and Xamarin. Finally within the application the message is passed to the Microsoft Band paired with the device.
I’m not going to post a complete step by step of the entire process (would just by way too long), instead I’ll be linking to the appropriate documentation as it was sufficient to get through all the set up work required to make this happen.

Setting up the CRM to Azure Service Bus Integration


This blog post by Matt Barbour does a great job of walking through the process of setting up the integration between CRM and Azure. No code – just configuration. The important part to keep in mind is you’ll need to use PowerShell to configure the Service Bus Endpoint as opposed to doing it through the Azure Portal. I used a Queue here as opposed to a Persistent Queue. The end result of this effort is to have the entire message context passed into the queue when a CRM message (think plug-in execution) is triggered. My original plan was to trigger this when a Task record was created. The more I thought about it and worked through the entire process I realized this probably wasn’t a good approach. Unless you’re doing some sort of integration/data mirroring sending every single record probably isn’t needed so there needs to be a way to limit what gets sent. Setting up the integration against an out of the box message alone doesn't give very much granularity as to when a message is sent. You could send all records effected by the chosen message but to be useful you’d inevitably need to write additional code some place to do some filtering. Instead of writing a bunch of code to handle the different types of messages coming from many different record types I simply created a new entity call “Push Notification”. It contains 2 important fields, one for the message (it will be fairly short to make sense on the Band) and a lookup to the recipient user. This does 2 things for us. First we can now use CRM’s own workflows to create the “Push Notification” record with just about any text in the system and also filtering it down to specific events – like a high dollar Opportunity was won. Secondly we only need to register one step against our Service Bus integration – when the “Push Notification” record is created.

2015-04-11_22-40-19

2015-04-11_22-35-38

To test this, create a new “Push Notification” record then go to System Jobs and you should see that is was sent to the Service Bus. Depending on how you registered the step (synchronously or asynchronously) it could be there right away or within a few seconds. I’d also recommend downloading the Service Bus Explorer, using this tool you’ll be able to connect to your Service Bus instance and see how many and the content of the messages in the queue.

2015-04-11_22-38-19

Setting up the Azure Notification Hub and Sending A Push Notification


I used this article as the basis for setting the Mobile Service using a .NET backend. I didn’t end up needing a database in this case as the messages sent from CRM are processed and immediately discarded. After the Mobile Service is created you can download a customized starter project to help you get started which contains projects for the back-end and mobile app. This project is a basic “Todo” application, all I needed was to have an app that just receives messages so I ended up deleting everything from the back-end project except the lone scheduled job. Once you've cleaned everything up the job needs to be modified to read the message from the queue and then send a push notification. You'll need to add some code to connect to the Notification Hub and then there is a bunch of boring code to parse the message XML and pull out the bits we need. Again I’d point you back at the Service Bus Explorer to be able to see the actual message content.

2015-04-11_22-44-39

Once you have the data for the push it’s just matter of formatting the message based on the platform you are sending to and sending it off. I was targeting iOS and in order to execute the code in the mobile which pushed to the Band when the app wasn’t actually in the foreground I needed to add in the “content-available” property. The other noteworthy item is that I’m using tags in my notification to target the specific user. If you look at the full code I am pulling out the “SystemUserId” of the user who was was designated as the recipient and I’m sending this as the second parameter which accepts a list of tags when sending the notification.

NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(
    NotificationHubConnectionString,
    NotificationHubName);

//content-available = 1 makes sure ReceivedRemoteNotification in 
//AppDelegate.cs get executed when the app is closed
var alert = "{\"aps\":{\"alert\":\"" + message + "\", \"content-available\" : \"1\"}}";  

//Would need to handle Windows & Android separately
await hub.SendAppleNativeNotificationAsync(alert, userid); 

You’ll be able to debug this from your local machine until you get it working properly, but once you do you can go ahead and publish to Azure. If you’ve been working with the starter project the correct publish profile should already be in place. Once that is done you can go into the Mobile Service under “Scheduler” and set your job up to run at regular intervals. The name for the job is the name of your class which inherits from “ScheduledJob“ minus “Job” – so in the example code “ProcessCrmQueueJob”  becomes “ProcessCrmQueue”. The lowest interval you can schedule for is every minute so for the duration of testing I would leave it unscheduled and just run it as you generate messages from CRM to speed up your testing. If every minute still isn’t quick enough later on you’d probably be better off creating some sort of queue listener and put it in Azure as a Web Job that continuously runs.

The next part is again a bunch of configuration. For every platform you want to send push notifications to you will need keys (Windows & Android) or a certificate (iOS) that need to be referenced in the Mobile Service. This article walks through the steps for each platform.

Setting Up the Xamarin iOS Application and Working with the Microsoft Band


I again started with the sample application I downloaded from Azure and again removed all the code relating the the “Todo” part of the application. Looking at the same Xamarin documentation in the above for setting up push notifications make sure you’ve followed all the steps to enable push notifications in the app for your platform. For iOS anyway there are a ton of steps and it is easy to make a mistake the first time going through (Windows and Android appear to be a bit easier to get going). Now would be a good time to download the sample code for the Xamarin Microsoft Band SDK. I ended up taking the storyboard from this application and replacing the one from the Azure download. You can also add the Band assembly from the Xamarin Component Store available from your project. In the screen I borrowed from Xamarin’s Band sample app I removed the the items related to the Band sensors and replaced with some fields to log in to CRM.

unnamed

I’ve used the code I wrote in this blog post to authenticate to CRM using SOAP only to log in and execute a WhoAmI request to get the “SystemUserId” based on the credentials. After getting back the value I’m storing it and then registering the application for push notifications.

async partial void LoginClick(UIButton sender)
{
    //Login/WhoAmI
    ...
    
    //Save the userid 
    NSUserDefaults.StandardUserDefaults.SetString(userid, "CrmUserId");

    //Register for notifications
    //Moved from AppDelegate.cs - FinishedLaunching
    var settings = UIUserNotificationSettings.GetSettingsForTypes(
        UIUserNotificationType.Alert
        | UIUserNotificationType.Badge
        | UIUserNotificationType.Sound,
        new NSSet());

    UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
    UIApplication.SharedApplication.RegisterForRemoteNotifications();
}

To make sure I am getting user specific messages from CRM I used the “SystemUserId” of the user as tag I was interested in received notifications for. I also included an “All Users” tag in case I wanted to expand in the future and have the ability to send a notification to all CRM users.

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    DeviceToken = deviceToken.Description;
    DeviceToken = DeviceToken.Trim('<', '>').Replace(" ", "");

    MobileServiceClient client = new MobileServiceClient(ApplicationUrl, ApplicationKey);

    string userid = NSUserDefaults.StandardUserDefaults.StringForKey("CrmUserId");
    if (string.IsNullOrEmpty(userid)) return;

    //Tags could be expanded to handle multiple different tags
    IEnumerable<string> tags = new List<string>() { userid, "All Users" };
    var push = client.GetPush();
    push.RegisterNativeAsync(DeviceToken, tags);
}

In order the interact with the Band your app needs to have its own tile and Xamarin’s sample application already had the code to add/remove so I just ended up tweaking it a bit and changing out the icon. As you would expect the sample already contains code to connect to the Band paired with your mobile device which you can execute using the button. Making someone push this button every time their phone restarts to ensure the app is connected to the Band isn’t very user friendly so I leveraged this same code to verify and connect to the Band if needed when a new push notification came in. From here it’s just a matter of picking apart the incoming message and pushing it over to the Band when received. Nothing more is required to display the the notification on the mobile device.

async public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
    if (null != userInfo && userInfo.ContainsKey(new NSString("aps")))
    {
        NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;

        string alert = string.Empty;
        if (aps.ContainsKey(new NSString("alert")))
        {
            var nsString = aps[new NSString("alert")] as NSString;
            if (nsString != null)
                alert = nsString.ToString();
        }

        if (!string.IsNullOrEmpty(alert))
        {
            //Show a pop-up if the application is open
            UIAlertView avAlert = new UIAlertView("CRM Item", alert, null, "OK", null);
            avAlert.Show();

            BandClient client = MainViewController.GetClient();

            //Connect to Band if not already connected
            if (client == null)
            {
                try
                {
                    BandClientManager manager = MainViewController.GetManager();
                    client = manager.AttachedClients.FirstOrDefault();
                    if (client == null) return;

                    //await MainViewController.ConnectToBand();
                    client = MainViewController.GetClient();
                }
                catch (BandException) { }
            }

            if (client == null) return;

            await client.NotificationManager.SendMessageTaskAsync(MainViewController.GetTileId(), "CRM Item",
                alert, DateTime.Now, true);
        }
    }
}

In the end you have something like this:

Start out by closing a $1,000,000+ Opportunity as Won

2015-04-12_20-26-19

The data is sent from CRM to the Azure Service Bus which generates a push notification sent to the Xamarin iOS app

IMG_0571

Finally the notification is sent from the Xamarin app to the Microsoft Band

2015-04-12_20-23-20

You can download all the code here:

https://github.com/jlattimer/CRMBandNotifications