How to integrate Dynamics 365 Plugin with Azure relay Hybrid connections without using Service end-point.

Follow Debajit’s Power Apps & Dynamics 365 Blog on WordPress.com

Recently I have been working on Azure integration with CRM a lot and frequently I see azure relay hybrid connection integration with Dynamics 365. And in most of the case, it is through registering the Service Endpoint in Plugin registration tool.

While the above works really great for most of the scenarios, sometimes it becomes necessary for us to post something else apart from CRM context information. Sometimes it’s not even important for us to have the whole context information pass through but some custom values to the listener based on some business logic.

Since I have been queried about that a lot, I decided to pen this one down for the benefit of my readers.

I am  not going to show here how to set up a relay with Hybrid connection enabled. There are awesome articles which explains these. Just as a pre-requisite I am assuming

  • Azure relay with Hybrid connection is set-up
  • The Hybrid connection is set for authorization
  • You have the Send and Listen shared access policies set up for the Hybrid connection

Screenshots of my Hybrid connection with sender and listener profiles with CRM acting as the sender.

image
image
image

Now coming to code.

The first thing is I set-up a plugin which will fire on create of account. To call the Relay Hybrid connection from my plugin, I use the awesome Microsoft.Azure.Relays Nuget package which I think is simple awesome.

image

Below is the code I write to invoke my Hybrid connection from my plugins.

public void Execute(IServiceProvider serviceProvider)
        {
             var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            SendToRelay(context).GetAwaiter().GetResult();
        }

        private async Task SendToRelay(IPluginExecutionContext context)
         {
            var hybridConnectionName = “<hybrid connection name>”;
             var relayUrl = “
<a href=”https://.servicebus.windows.net”;”>.servicebus.windows.net”;’>https://<your relay name>.servicebus.windows.net”; // put your relay URL without the hybrid connection name
            var connectionKey = “<primary key for the sender profile>“;// put your primary key for the sender profile
            var keyName = “Sender”;

            var token = TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, connectionKey);
            var uri = new Uri($”{relayUrl}/{hybridConnectionName}”);

            var relayToken = await token.GetTokenAsync(uri.AbsoluteUri, TimeSpan.FromMinutes(30));

            HttpClient client = new HttpClient();

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
            request.Content = new StringContent($”{context.PrimaryEntityName}”, Encoding.UTF8, “application/json”);

            request.Headers.Add(“ServiceBusAuthorization”, relayToken.TokenString);
            request.Headers.Add(“CrmMessageName”, context.MessageName);

            client.SendAsync(request);
}

You would need to replace the one highlighted in yellow with appropriate values from your azure environment. As you can see from the above code I can pass my own data in the body of the request as well as pass some custom data in the headers collection. And as I using the Microsoft.Azure.Relay assemblies I need to do ILMERGE to merge this assembly with the plugin dll. For this I again use the wonderful MsBuild.IlMerge task available in Nuget

image

I am not awaiting for the result to come back since my relay can perform some lengthy operations. However in case I want to get the return values from my relay listener, I can just change the last few lines like this.

var responseMessage = await client.SendAsync(request);
            var content = await responseMessage.Content.ReadAsStringAsync();

Now coming to the listener, I just create a console application and keep it running. Below is the sample code for a listener. The code is courtesy Microsoft Docs and is also using Microsoft.Azure.Relays Nuget package.

static async Task RelayListener()
        {
            // create a connection string with the listener profile
            HybridConnectionListener listener = new HybridConnectionListener(“<put the connecting string of Hybrid listener>“);

            listener.Connecting += (o, e) => { Console.WriteLine(“Listener is connecting to Azure…”); };
            listener.Offline += (o, e) => { Console.WriteLine(“Listener is about to go offline…”); };
            listener.Online += (o, e) => { Console.WriteLine(“Listener is online…”); };

            listener.RequestHandler = (context) =>
            {
                 StreamReader streamReader = new StreamReader(context.Request.InputStream);
                // reading the body
                 var requestContent = streamReader.ReadToEnd();

                // reading the headers
                foreach(var header in context.Request.Headers)
                {
                    //Console.WriteLine($”Header Key: {header}, Header Value:{context.Request.Headers[0]}”)
                }
            };

            await listener.OpenAsync();

            await Console.In.ReadLineAsync();

            await listener.CloseAsync();
        }

And finally with my console running, if I create an account, the relay listener immediately catches this.

image

Wonderful isn’t it?

Hope this helps

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)