Write a Service Bus Event Listener that consumes Microsoft Dataverse messages

Completed

Types of supported Service Bus contracts

Microsoft Dataverse supports a variety of methods to consume Azure Messaging Service Bus queue messages: queue, one-way, two ways, or REST. If using two-way and REST, you are able to return a string of information back to Dataverse.

Queue

Queue listeners are not required for this type of queue. You can consume queued messages in a "destructive" or "non-destructive" read. A destructive read will read the message from the queue and remove it, whereas a non-destructive read will not remove the message from the queue. This method is useful for "send-and-forget" scenarios where it is not critical that the message is received at a given point of time.

Topic

Topic listeners are similar to queue listeners, except that one or more listeners can subscribe to receive messages for a given topic. This type is useful if you require multiple consumers for a given message.

One-way

One-way contracts require that an active event listener be available to consume a message that is posted to the Service Bus queue. If no active listener is available, the post will fail. If the post fails, Dataverse will retry posting the message in exponentially larger and larger time spans until the asynchronous system job is eventually canceled. In this case, the System Job status of this event will be set to Failed.

Two-way

Two-way contracts are similar to one-way contracts, except that they also provide the ability to return a string value from the listener. If you've registered a custom Azure-aware plug-in to post your message, you can then consume this returned data within your plug-in. A common application of this scenario might be if you want to retrieve the ID of a record that was created in an external system as part of your listener's process to maintain it in your Dataverse environment.

REST

REST contracts are similar to two-way contracts except that it is exposed on a REST endpoint.

Write a queue listener

In the previous exercise, you registered a Service Endpoint that publishes messages to a Service Bus Endpoint whenever account data is updated in your Dataverse environment. This exercise now describes how to consume those messages.

  1. Create a C# Console Application in Visual Studio that targets .NET 4.6.2 or higher.

  2. Add the following NuGet packages:

    • Azure.Messaging.ServiceBus

    • Microsoft.CrmSdk.CoreAssemblies

  3. In the application's Main method, paste the following code. Replace the Endpoint URL with your Azure Service Bus Namespace's Endpoint URL and the queue name if it differs:

    string connectionString =@"[ENDPOINT URL]";
    string queueName = "mslearnsamplequeue";
    QueueClient queueClient = QueueClient.CreateFromConnectionString(connectionString, queueName, ReceiveMode.PeekLock);
    
  4. To consume your message, use the "OnMessage" method, which provides the ability to process a Service Bus queue message in an event-driven message pump.

    queueClient.OnMessage(message =>
                {
                    //get RemoteExecutionContext based on Message Format
                    RemoteExecutionContext context = null;
    
                    if (message.ContentType == "application/msbin1") //.NETBinary Message Format
                    {
                        context = message.GetBody<RemoteExecutionContext>();
                    }
                    else if (message.ContentType == "application/json") //JSON Message Format
                    {
                        context = message.GetBody<RemoteExecutionContext>(
                                          new DataContractJsonSerializer(typeof(RemoteExecutionContext)));
                    }
                    else if (message.ContentType == "application/xml") //XML Message Format
                    {
                        context = message.GetBody<RemoteExecutionContext>(
                            new DataContractSerializer(typeof(RemoteExecutionContext)));
                    }
                    try
                    {
                    var target = context.InputParameters["Target"] as Entity;
    
                    foreach (var field in target.Attributes)
                    {
                        Console.WriteLine($"Name: {field.Key} Value: { field.Value}");
                    }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                });
    
  5. Lastly we are going to add a Console.ReadLine() to our main method to allow for multiple messages to be processed. Note this is not a scalable method for handling event-processing however is sufficient enough for our exercise’s purposes. You’d want to have a more scalable solution that you host in an Azure Durable function or other service of your preference.

    Console.ReadLine();
    
  6. Hit F5 to run your application. If there are already messages in your queue from your previous exercise, they should get processed and their message contents should be displayed on the console screen. If not, you can invoke an update by making an update to an Account in your Dataverse environment.