azure-functionsazureservicebusservicebus

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.


Solution

  • 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;
        }
    }