Search code examples
c#asp.net.netazure

Azure Service Bus Isolated Function middleware - add correlation ID onto ServiceBusReceivedMessage


I'd like to understand the possibility and method for modifying the correlation ID property of a ServiceBusReceivedMessage within a middleware. If this isn't achievable, I'm open to alternative suggestions for executing the action mentioned prior/earlier than the actual function.

.NET 6 isolated function v4

   public class MiddlewareA : IFunctionsWorkerMiddleware
    {
        public Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
        {
            // access the ServiceBusReceivedMessage, evaluate its properties like 
            // correlationId and update if it does not exist
            return next.Invoke(context);
        }
    }

Solution

  • For now you cannot modify the CorrelationID as its a Read-only property of Azure Service Bus That is part of its properties. It is similar to Content Type, To ReplyTo just like other types of message patterns.

    But you can deserialize your Service Bus Properties including CorrelationID and pass it in the code to output message as referenced in this Github Issue1 and Github Issue2 and Github Issue3

    Below is my custom middleware that logs the CorrelationID, You can use this CorrelationId in your output messages like below:-

    My CorrelationIdMiddleware.cs:-

    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Azure.Functions.Worker.Middleware;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp66
    {
        public class CorrelationIdMiddleware : IFunctionsWorkerMiddleware
        {
            private readonly ILogger<CorrelationIdMiddleware> _logger;
    
            public CorrelationIdMiddleware(ILogger<CorrelationIdMiddleware> logger)
            {
                _logger = logger;
            }
    
            public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
            {
                if (context.BindingContext.BindingData.TryGetValue("ServiceBusTrigger", out var triggerData)
                    && triggerData is ServiceBusReceivedMessage receivedMessage)
                {
                    if (receivedMessage.ApplicationProperties.ContainsKey("CorrelationId"))
                    {
                        var correlationId = (string)receivedMessage.ApplicationProperties["CorrelationId"];
    
                        // Log the correlation ID without modifying the message
                        _logger.LogInformation("Correlation ID: {correlationId}", correlationId);
                    }
                }
    
                await next(context);
            }
        }
    }
    

    My Function1.cs:-

    using System;
    using Azure.Messaging.ServiceBus;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp66
    {
        public class Function1
        {
            private readonly ILogger<Function1> _logger;
    
            public Function1(ILogger<Function1> logger)
            {
                _logger = logger;
            }
    
            [Function(nameof(Function1))]
            public void Run([ServiceBusTrigger("myqueue", Connection = "myqueue")] ServiceBusReceivedMessage message)
            {
                _logger.LogInformation("Message ID: {id}", message.MessageId);
                _logger.LogInformation("Message Body: {body}", message.Body);
                _logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);
                _logger.LogInformation("Message Content-Type: {contentType}", message.CorrelationId);
            }
        }
    }
    

    My Program.cs:-

    using FunctionApp66;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureServices(services =>
        {
            services.AddApplicationInsightsTelemetryWorkerService();
            services.ConfigureFunctionsApplicationInsights();
            services.AddSingleton<CorrelationIdMiddleware>();
    
        })
        .Build();
    
    host.Run();
    

    Output:-

    enter image description here