Integrate Dynamics 365 Plugin with Azure relay Hybrid connections. And it’s not using service endpoint

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at

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.


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.


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));


        private async Task SendToRelay(IPluginExecutionContext context)
            var hybridConnectionName = “<hybrid connection name>”;
             var relayUrl = “
<a href=”;;”>”;’>https://<your relay name>”; // 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);



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


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.


Wonderful isn’t it?

Hope this helps

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit or reach out to us at

Our product offerings:

Role based views for Dynamics 365 (

CRM-Sharepoint Attachment uploader and metadata manager (

Record Cloner for Dynamics 365 (

Multiselect picklist for Dynamics 365 (

Leave a Reply