Showing posts with label Azure Service Bus. Show all posts
Showing posts with label Azure Service Bus. Show all posts

Jul 2, 2018

Pass Dynamics 365 execution context to ASB (TwoWay), use Listner and retrieve back via Azure Aware Plug-in

Last time we understood how to pass the Dynamics 365 Plug-in context to Azure Service Bus without a Queue, but with a Listener. Let's extend our experience by using a TwoWay Designation type and Azure Aware Plug-in to retrieve contact back from end-point.

a) Register TwoWay Endpoint

As we did many times, Copy the Connection String from Policy of Azure Service Bus.


Now copy in the Service End Point entry of Plug-in Registration Tool.


In resulting detail page, change do below changes;
a. Select TwoWay for the Designation Type
b. Add https: to Namespace Address
c. Give a name to Path.


b) Implement Listener

Now implement below Listener code in new Console Application.

Need to install below Nuget Packages;
a. Microsoft.Crm.Sdk.CoreAssemblies
b. WindowsAzure.ServiceBus

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.ServiceBus.Messaging;
using System.Runtime.Remoting.Contexts;
using System.ServiceModel;
using Microsoft.ServiceBus;

namespace AsbListnerTwoWay
{
    class Program
    {
        static void Main(string[] args)
        {
            string asbAccessKeyName = "Sum1ServiceBusPolicy";
            string asbAccessKey = "7WxSLRMvYF0A3HbLUgfQeqIEb1eKsHgg5mrUwc=";
            string asbEndPoint = "https://sumeservicebus1.servicebus.windows.net";

            var serviceHost = new ServiceHost(typeof(TwoWayServiceEndpoint));
            var transportClient = new TransportClientEndpointBehavior(TokenProvider.CreateSharedAccessSignatureTokenProvider(asbAccessKeyName, asbAccessKey));
            serviceHost.AddServiceEndpoint(typeof(ITwoWayServiceEndpointPlugin), new WS2007HttpRelayBinding(), asbEndPoint).EndpointBehaviors.Add(transportClient);
            serviceHost.Open();
            Console.ReadLine();
        }
    }

    public class TwoWayServiceEndpoint : ITwoWayServiceEndpointPlugin
    {
        string ITwoWayServiceEndpointPlugin.Execute(RemoteExecutionContext executionContext)
        {
            string message = executionContext.PrimaryEntityId.ToString();
            Console.WriteLine("Record Id : {0}", message);
            return message;
        }
    }
}

c) Implement Azure Aware Plug-in

Now read Service End Point Id by going to properties of the entry we created in first step as below;


..and implement a Plug-code (for Account Post Create). This code consist of Service End Point reference which uses the Id we read above.

using System;
using Microsoft.Xrm.Sdk;

namespace SumeTrial3Plugin
{
    public class AccountPostCreate : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            Guid serviceEndPointId = new Guid("63c5c746-e07d-e811-a967-000d3ad1c0d2");
            IPluginExecutionContext pluginContext = 
                (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IServiceEndpointNotificationService service = 
                (IServiceEndpointNotificationService)serviceProvider.GetService(typeof(IServiceEndpointNotificationService));

            try
            {
                tracingService.Trace("Passing Context to Service Endpoint");
                string response = service.Execute(new EntityReference("serviceendpoint",serviceEndPointId), pluginContext);
                if (!String.IsNullOrEmpty(response))
                {
                    tracingService.Trace("response : {0}", response);
                }
                tracingService.Trace("Plug-in completed");
            }

            catch (Exception ex)
            {
                tracingService.Trace("Error: {0}", ex.Message);
                throw;
            }
        }
    }
}

Then register this plug-in as usual through Plug-in registration tool.


d) Test the operation

Now execute the Console Application (Listener) and Create an Account in Dynamics 365. You will notice below two;

1) Console Application/ Listener program pics the Context and write the Id.


2) If you check, Plug-in Trace Log, you will see the response has been retrieved by the Plug-in back.


Jun 29, 2018

Pass Dynamics 365 execution context to Azure Service Bus (OneWay) and read through Console Application (Listener)

In previous post, we understood how to pass the Dynamics 365 execution context to Azure Service Bus Queue and read through a Console App. Lets see how to pass the execution context to be read through a Listener bind to the endpoint. Here we don't use a Queue. (In our previous post we have also shown how to configure ASB from scratch).

1) Create a Service Policy in ASB

This time create a Shared Access Policy for Azure Service Bus in root level.


Once created, we can see all the details once open it. Copy Primary Connection String of the Policy.


2) Register Service End Point

Now Open the Plug-in Registration Tool and go to Register > New Service Endpoint which results a pop-up. Now paste the Primary Connection String we copied in previous step.


Now do below changes in resulting Service Endpoint entry;

a. Select OneWay for the Designation Type
b. Add https: to Namespace Address
c. Give a name to Path.


Now register a step for Lead entity for Create message. Make sure you register this in Asynchronous mode.


Now go to D365 and create a Lead record and check System Jobs, where you will notice an exception since there is no listener for endpoint as below;


3) Implement Listener to Endpoint

Let's implement a listener for the endpoint through a Console Application.

For that below NuGet Packages needed to be installed;
a. Microsoft.Crm.Sdk.CoreAssemblies
b. WindowsAzure.ServiceBus

Also notice that we have used Policy Name and Key (i.e. Primary Key) from the Policy we created.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.ServiceBus.Messaging;
using System.Runtime.Remoting.Contexts;
using System.ServiceModel;
using Microsoft.ServiceBus;

namespace AzureServiceBusListener
{
    class Program 
    {
        static void Main(string[] args)
        {
            string asbAccessKeyName = "Sum1ServiceBusPolicy";
            string asbAccessKey = "7WxSLRMvYF0myA3HbLUgfQeqIEb1eKsHgg5mrUwc=";
            string asbEndPoint = "https://sumeservicebus1.servicebus.windows.net";

            var serviceHost = new ServiceHost(typeof(TestRemoteService));
            var transportClient = new TransportClientEndpointBehavior(
                TokenProvider.CreateSharedAccessSignatureTokenProvider(asbAccessKeyName, asbAccessKey));
            serviceHost.AddServiceEndpoint(typeof(IServiceEndpointPlugin),
                new WS2007HttpRelayBinding(), asbEndPoint).EndpointBehaviors.Add(transportClient);
            serviceHost.Open();
            Console.ReadLine();
        }
    }

    public class TestRemoteService : IServiceEndpointPlugin
    {
        public void Execute(RemoteExecutionContext executionContext)
        {
            Console.WriteLine("Entity Name : {0}, Record Id : {1}", 
                executionContext.PrimaryEntityName, executionContext.PrimaryEntityId);
        }
    }
}

Now run this program and start Creating Leads. Now you will notice Listener is picking the context each time a new Lead is Created.


References;
https://blogs.msdn.microsoft.com/swetagu/2016/04/12/crm-azure-service-endpoint-and-listener-deep-dive/
https://nishantrana.me/2017/03/22/configure-dynamics-365-and-azure-service-bus-integration-using-oneway-relay-and-listener/
https://msdn.microsoft.com/en-us/library/gg334377.aspx

Jun 27, 2018

Pass Dynamics 365 execution context to Azure Service Bus Queue and Consume through a Console Application

This is the first exercise I performed to see how Dynamics 365 can be integrated with Azure Service Bus.

1) Configure Azure Service Bus and a Queue

Search for Azure Service Bus in Azure and create one. I have given below details. SumeRG1 is my existing Resource Group.


One its ready I would like to create a Queue by selecting it through menu items as below.


Below shows details I gave in in Queue.


Now I create a Shared Policy.


Once save the policy you will be able to see all the policy details including the Primary Connection String, which we need to copy.


2) Pass the context through

Now connect to your Dynamics 365 instance in Plug-in Registration Tool and go to Register > New Service Endpoint which result a dialog box. Now Paste the Primary Connection String we copied in previous step.


Then you will see how Service End Point Details get populated.


Now add a new step to newly registered Service End point entry in Plug-in Registration Tool. In my example I am adding Create Message of Contact.


Now Create a Contact in Dynamics 365 and notice one message has been pushed to d365azurequeue as below;


3) Consume the Queue Item through a Console Application

To consume the Queue Item I am creating a Console Application. Make sure you add below NuGet Packages to your application.


..and below is my code. Please note this Connection String is the same one we used to connect to Plug-in Registration Tool, which we copied from SAS Policy.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ServiceBus.Messaging;
using Microsoft.Xrm.Sdk;
using System.Runtime.Remoting.Contexts;

namespace ReadAzureServiceBus
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Testing Azure Service Bus Queue Records pushed from D365");

            var connectionStr = "EntityPath=d365azurequeue;Endpoint=sb://sumeservicebus1.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=FcM+XYZSL7FOVIMXJIdg0Gk1uK3ipU51hUSrC50N4UyCTo=";

            var client = QueueClient.CreateFromConnectionString(connectionStr);

            client.OnMessage(message =>
            {
                var context = message.GetBody<RemoteExecutionContext>();
                Console.WriteLine("Entity Name : {0} and Id : {1} ", context.PrimaryEntityName, context.PrimaryEntityId);
            });
            
            Console.ReadLine();
        }
    }
}

Once execute I get below result as expected;


Interestingly, if you refresh the Queue in Azure Service Bus, we can see Queue Item has been consumed (i.e. removed).

This is actually the fundamental idea of using Azure Service Bus for integration of Dynamics 365 with third party applications. I find this cool ! You know why, not like many other integration techniques we use, here we can see message is being added to the queue and stay in waiting status to be consumed. In fact, this decoupling is significant and nothing get lost in thin air.

References;
https://community.dynamics.com/365/b/xrmandbeyond/archive/2017/11/11/message-queueing-in-dynamics-365-with-azure-service-bus
https://nishantrana.me/2017/03/22/configure-dynamics-365-and-azure-service-bus-integration-through-queue-and-queueclient/