FactoryOptimizr
FactoryOptimizr

Reputation: 326

Service Bus Message Properties in Azure Functions?

I've seen some older posts on this topic, but nothing up-to-date and related to the newer Service Bus and Azure Functions stacks, so thought I'd ask the question again.

On an Azure Function using a Service Bus Trigger, is there a way to access the Service Bus message properties? As far as I can see, it seems that only the message body string is passed into the Run method.

Similarly, on an Azure Function using a Service Bus output binding, is there a way to add message properties to the outbound Service Bus message? Again, as far as I can see, it seems the output binding will only accept a message body string.

Upvotes: 5

Views: 10256

Answers (3)

FactoryOptimizr
FactoryOptimizr

Reputation: 326

Here's example code for an Azure Function that contains a Service Bus trigger to intercept incoming messages AND a Service Bus output binding to send a reply message. In both cases, a Service Bus Message object -- containing message properties -- is used as the message payload.

Note that this example uses the (slightly older) Microsoft.Azure.ServiceBus library, and NOT the (newest and latest) Azure.Messaging.ServiceBus library. As @Sean-Feldman noted in his reply, properties are handled differently in this newest library.

public static class StackOverflowExample
{
    // Azure Service Bus constants
    private const string ServiceBusTopic = "ServiceBusRequest"; // Use your own topic name
    private const string ServiceBusReplyTopic = "ServiceBusReply"; // Use your own reply topic name
    private const string ServiceBusSubscription = "AzureFunctionSubscription"; // Use your own subscription name
    private const string ServiceBusConnectionString = "ServiceBusConnectionString"; // As you've defined it in local.settings.json

    [FunctionName("AzureFunctionServiceBus")]  // Use your own Azure Function name
    public static void Run(
        [ServiceBusTrigger(topicName: ServiceBusTopic, subscriptionName: ServiceBusSubscription, Connection = ServiceBusConnectionString)] Message inputMessage, 
        ILogger log,  // Service Bus trigger
        [ServiceBus(ServiceBusReplyTopic, EntityType = EntityType.Topic, Connection = ServiceBusConnectionString)] out Message outputMessage) // Service Bus output binding
    {
        // Get the message body from the incoming message object.
        string inputMessageBody = Encoding.UTF8.GetString(inputMessage.Body);

        // Get the message properties from the incoming message object.
        // (You can use message properties however you want. In this example,
        // we'll just feed them back into the output message.)
        IDictionary<string, object> messageProperties = inputMessage.UserProperties;

        // Deserialize the incoming message body.
        // (Assumes your own class object is serialized as the incoming message payload.)
        InputClass inputMessageObject = JsonConvert.DeserializeObject<InputClass>(inputMessageBody);

        // Do some work here...

        // Create an output message object.
        // (Assumes your own class object is the basis of the output message payload.)
        OutputClass replyMessageObject = new OutputClass(
            requestMessage: inputMessageObject, requestReceivedDateTimeUtc: DateTime.UtcNow,
            serviceBusReplyTopic: ServiceBusReplyTopic, status: "Success",statusMessage: tring.Empty);
        
        // Serialize the output message object
        string replyMessageBody = JsonConvert.SerializeObject(replyMessageObject);

        // Build a Message object for the output message.
        // (The outputMessage variable is defined as an "out" parameter above in the Service Bus output binding.
        // The Service Bus output binding picks up the outputMessage when the Azure Function completes.)
        outputMessage = BuildMessageObject(replyMessageBody, messageProperties);
    }


    // Static method to build and return a Service Bus Message object given a message string
    // and a dictionary of message properties.
    private static Message BuildMessageObject(string message, IDictionary<string, object> messageProperties = null)
    {
        // Create the Service Bus message object
        Message messageObject = new Message(Encoding.UTF8.GetBytes(message));

        // Add message properties, if defined
        if (messageProperties != null)
        {
            foreach (var messageProperty in messageProperties)
            {
                messageObject.UserProperties.Add(messageProperty);
            }
        }

        // Return the message object
        return messageObject;
    }
}

Upvotes: 2

user8862383
user8862383

Reputation: 51

Use the ServiceBusReceivedMessage clas instead of the string message. It has an ApplicationProperties to read the message properties

Upvotes: 4

Sean Feldman
Sean Feldman

Reputation: 25994

Yes, you can. The details of how to depend on the binding library you're using and the SDK it depends on. Microsoft documentation is not bad to start with. Message properties and user properties are available both. See https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus-trigger for more details.

Note that with the latest Service Bus SDK Azure.Messaging.ServiceBus and the new Functions Isolated Worker SDK access to the properties is somewhat different and requires deserialization of JSON values provided via function execution context.

Upvotes: 0

Related Questions