Search code examples
c#azureazure-functionsazureservicebus

How can you set the MessageId of a service bus message using the Azure Functions output binding and IAsyncCollector?


I'm currently publishing a message to an Azure service bus using output binding and IAsyncCollector like so.

[FunctionName(nameof(ReceiveTransaction))]
[OpenApiOperation(nameof(ReceiveTransaction), "Transaction", Description = "Receives a transaction and adds to the Transaction Platform")]
[OpenApiRequestBody("application/json", typeof(string), Description = "Parameters", Required = true)]
[OpenApiResponseWithoutBody(HttpStatusCode.BadRequest, Description = "Request was invalid and could not be processed")]
[OpenApiResponseWithoutBody(HttpStatusCode.OK, Description = "Request was valid - transaction posted to platform")]
public async Task<IActionResult> ReceiveTransaction(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "v1/receiveTransaction")] HttpRequest req,
    [ServiceBus("%Transactions:SB:Transactions:IngressQueue%", Connection = "Transactions:SB:Transactions")] IAsyncCollector<string> collector,
    ILogger logger)
{
    try
    {
        using var sr = new StreamReader(req.Body);

        var rawJson = await sr.ReadToEndAsync();

        var tran = JsonConvert.DeserializeObject<RetailTransaction>(rawJson, JsonSerialisationUtils.SerialiserSettings);
        tran.UpdateExtendedProperties();
        tran.SetPlatformReceived();

        logger.LogInformation(StandardEvents.SuccessEvent, "Incoming transaction: {transactionNumber} validated", tran.TransactionNumber);

        var queueMessage = JsonConvert.SerializeObject(tran, JsonSerialisationUtils.SerialiserSettings);
        await collector.AddAsync(queueMessage);
        logger.LogInformation($"Received transaction added to servicebus queue");
        
        return new NoContentResult();
    }
    catch (Exception ex)
    {
        logger.LogError(StandardEvents.FailureEvent, ex, "Unhandled exception");
    }

    throw new ArgumentException("Bad Request");
}

Solution

  • A collector is designed to dispatch one or more messages. Because your collector is of type string, you can only provide the body of each message that will be sent. Changing the type to an SDK type would allow you to set the standard properties.