Write a listener application for an Azure solution

This topic describes how to write an Azure solution listener application that can read and process Microsoft Dataverse messages that are posted to the Azure Service Bus. As a prerequisite, you should familiarize yourself with how to write a Azure Service Bus listener before trying to learn the specifics of a Dataverse listener. For more information, see the Azure Service Bus documentation.

Write a queue listener

A message queue is a repository of messages received at a Service Bus endpoint. A queue listener is an application that reads and processes these queued messages. Because the Service Bus messages are stored in a queue, a listener doesn't have to be actively listening for messages to be received in the queue. A queue listener can be started after messages have arrived in the queue and still process those messages. Other types of listeners discussed in the next section must be actively listening or they will miss the opportunity to read a message. These messages can originate from Dataverse or from some other source.

Important

When writing a queue listener, check each message header action to determine if the message originated from Dataverse. For information on how to do this see Filter messages.

You can do a destructive message read using Receive in ReceiveMode.ReceiveAndDelete mode, where the message is read and removed from the queue, or a non-destructive read using ReceiveMode.PeekLock mode, where the message is read but still available in the queue. For more information about reading messages from a queue, see How to receive messages from a queue.

A topic is similar to a queue but implements a publish/subscribe model. One or more listeners can subscribe to the topic and receive messages from its queue. More information: Queues, topics, and subscriptions

Important

To use these queue or topic contracts, you must write your listener applications using the Azure SDK.

Use of queues and topics in your multi-system software design can result in the decoupling of systems. If the listener application ever becomes unavailable, the message delivery from Dataverse will still succeed and the listener application can continue processing the queue message when it is back online. More information: Queues, topics, and subscriptions

Write a one-way, two-way, or REST listener

In addition to the queue listener described previously, you can write a listener for three other Service Bus contracts that are supported by Dataverse: one-way, two-way, and REST. A one-way listener can read and process a message posted to the Service Bus. A two-way listener can do the same but can also return a string of some information back to Dataverse. A REST listener is the same as the two-way listener except that it works with a REST endpoint. Notice that these listeners must be actively listening at a service endpoint to read a message sent over the Service Bus. If the listener isn't listening when Dataverse attempts to post a message to the Service Bus, the message doesn't get sent.

Writing a listener is structured around what is known as ABC: address, binding, and contract.

One-way listener

After your listener is registered with an endpoint, the listener's Execute method is invoked whenever a message is posted to the Service Bus by Dataverse. The Execute method doesn't return any data from the method call. For more information, see the one-way listener sample, Sample: One-way listener.

Two-way listener

For this two-way contract, the Execute method returns a string from the method call. For more information, see the two-way listener sample, Sample: Two-way listener.

REST listener

For the REST contract, the Execute method returns a string from the method call. Refer to the REST listener sample, Sample: REST listener, for more information. Notice that in the REST listener sample, a WebServiceHost is instantiated and not a ServiceHost as was done in the two-way sample.

Note

When using the out-of-box (ServiceBusPlugin) plug-in with a two-way or REST listener, the plug-in doesn't use any string data returned from the listener. However, a custom Azure-aware plug-in could make use of this information.

When you run the listener samples, the issuer secret you're prompted for is the Azure Service Bus management key. The WS2007 Federation HTTP binding uses token mode and the WS-Trust 1.3 protocol.

Filter messages

There is a property bag of extra information added to each brokered message Properties property sent from Dataverse. The property bag, available with queue, relay, and topic contract endpoints, contains the following information:

  • Organization URI
  • Calling user ID
  • Initiating user ID
  • Table logical name
  • Request name

This information identifies the organization, user, table, and message request being processed by Dataverse that resulted in the Service Bus message being posted. The availability of these properties indicates that the message was sent from Dataverse. Your listener code can decide how to process the message based on these values.

Read the data context in multiple data formats

The data context from the current Dataverse operation is passed to your Azure solution listener application in the body of a Service Bus message. In previous releases, only a .NET binary format was supported. For cross-platform (non-.NET) interoperability, you can now specify one of three data formats for the message body: .NET Binary, JSON, or XML. This format is specified in the MessageFormat column of the ServiceEndpoint Table.

When receiving messages, your listener application can read the data context in the message body based on the contentType of the message. Sample code to do so is shown below.

var receivedMessage = inboundQueueClient.Receive(TimeSpan.MaxValue);  
  
if (receivedMessage.ContentType == "application/msbin1")  
{  
    RemoteExecutionContext context = receivedMessage.GetBody<RemoteExecutionContext>();  
}  
else if (receivedMessage.ContentType == "application/json")  
{  
    //string jsonBody = new StreamReader(receivedMessage.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();  
    RemoteExecutionContext contextFromJSON = receivedMessage.GetBody<RemoteExecutionContext>(  
        new DataContractJsonSerializer(typeof(RemoteExecutionContext)));  
}  
else if (receivedMessage.ContentType == "application/xml")  
{  
    //string xmlBody = new StreamReader(receivedMessage.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();  
    RemoteExecutionContext contextFromXML = receivedMessage.GetBody<RemoteExecutionContext>(  
        new DataContractSerializer(typeof(RemoteExecutionContext)));  
}  

See also

Azure extensions
Write a custom Azure-aware plug-in
Sample: One-way listener
Sample: Two-way listener
Sample: REST listener
Work with Dataverse data in your Azure solution
Work with Dataverse event data in your Azure Event Hub solution