Reputation: 2967
I am trying to use Azure function output bindings to send message to a service bus topic having one subscription
Following piece of code is doing the job but I am not able to set
[Function(nameof(Function1))]
[ServiceBusOutput("test-topic", Connection = "CONN")]
public async Task<OutputData> Run(
[ServiceBusTrigger("test-queue", Connection = "CONN")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions,
ICollector<BrokeredMessage> collector
)
{
//Following return
//Is there any way to set custom properties of this message?
//Along with custom property, I would also like to set messageProperty contentType to application/json
OutputData outputData = new OutputData
{
ID = 123,
Name = "Test"
};
// Complete the message
await messageActions.CompleteMessageAsync(message);
return outputData;
/*As per solution mentioned [here](https://stackoverflow.com/questions/50457428/custom-message-properties-on-azure-queue-topic-message-from-azure-function), I tried to set custom properties but collector is always null.*/
BrokeredMessage brokeredMessage = new();
brokeredMessage.ContentType = "application/json";
brokeredMessage.Properties.Add("ID", 123);
brokeredMessage.Properties.Add("Name", "Test");
//Injecting ICollector<BrokeredMessage> notworking as its always null.
//collector.Add(brokeredMessage);
}
I can see outputData
has reached to its destination but content type is text/plain
and I can't add any custom properties.
I am using
Any pointers ?
UPDATE 1
As suggested by @Dasari Kamali I tried using ServiceBusMessage
but still observing same behavior
#region ServiceBusMessage not working
ServiceBusMessage serviceBusMessage = new ServiceBusMessage();
serviceBusMessage.ContentType = "application/json";
serviceBusMessage.ApplicationProperties.Add("ID", 123);
serviceBusMessage.ApplicationProperties.Add("Name", "Test");
serviceBusMessage.Body = BinaryData.FromString("Test");
#endregion
// Complete the message
await messageActions.CompleteMessageAsync(message);
return serviceBusMessage;
Upvotes: 0
Views: 101
Reputation: 2967
It looks like using built-in output bindings we can not add ApplicationProperties
. I end up using IAzureClientFactory<ServiceBusSender>
to create instance of service bus topic client. And subsequently used ServiceBusMessage
to send message to service bus topic by setting ApplicationProperties
builder.Services.AddAzureClients(builder =>
{
builder.AddServiceBusClient(conn);
builder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, sp) =>
{
var sbClient = sp.GetRequiredService<ServiceBusClient>();
var sender = sbClient.CreateSender("test-topic");
return sender;
}).WithName("test-topic");
});
public Function1(ILogger<Function1> logger, IAzureClientFactory<ServiceBusSender> sbSender)
{
_clientFactory = sbSender;
}
[Function(nameof(Function1))]
public async Task Run(
[ServiceBusTrigger("test-queue", Connection = "CONN")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions
)
{
OutputData outputData = new OutputData
{
ID = 123,
Name = "Test"
};
#region Working - Use IAzureClientFactory to send message
var topic = _clientFactory.CreateClient("test-topic");
var serviceBusMessage = new ServiceBusMessage(JsonConvert.SerializeObject(outputData))
{
ContentType = "application/json"
};
serviceBusMessage.ApplicationProperties.Add("ID", 123);
await topic.SendMessageAsync(serviceBusMessage);
#endregion
// Complete the message
await messageActions.CompleteMessageAsync(message);
}
Complete code is available here - azure-sb-topic-output-binding
Upvotes: 0
Reputation: 3649
I tried your code and got the same issue, so I tried using a ServiceBusQueue trigger function instead.
It manually creates a ServiceBusSender
from a ServiceBusClient
and explicitly sends the message using SendMessageAsync()
. It successfully worked for me to send message to a Service Bus Topic and setting the ContentType
as application/json
and Custom Properties.
using System.Text;
using Azure.Messaging.ServiceBus;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace FunctionApp24
{
public class Function1
{
private readonly ILogger<Function1> _logger;
private readonly ServiceBusClient _serviceBusClient;
public Function1(ILogger<Function1> logger, ServiceBusClient serviceBusClient)
{
_logger = logger;
_serviceBusClient = serviceBusClient;
}
[Function(nameof(Function1))]
public async Task Run(
[ServiceBusTrigger("kamqueue", Connection = "CONN")] ServiceBusReceivedMessage receivedMessage,
ServiceBusMessageActions messageActions)
{
_logger.LogInformation("Received Message ID: {id}", receivedMessage.MessageId);
_logger.LogInformation("Received Content-Type: {contentType}", receivedMessage.ContentType);
_logger.LogInformation("Received Body: {body}", Encoding.UTF8.GetString(receivedMessage.Body.ToArray()));
var outputData = new
{
ID = 123,
Name = "Test"
};
string jsonString = JsonConvert.SerializeObject(outputData);
byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonString);
var serviceBusMessage = new ServiceBusMessage(jsonBytes)
{
ContentType = "application/json",
MessageId = Guid.NewGuid().ToString(),
CorrelationId = receivedMessage.CorrelationId ?? Guid.NewGuid().ToString(),
ReplyTo = receivedMessage.ReplyTo,
SessionId = receivedMessage.SessionId,
PartitionKey = receivedMessage.PartitionKey,
TimeToLive = TimeSpan.FromMinutes(10)
};
serviceBusMessage.ApplicationProperties["ID"] = 123;
serviceBusMessage.ApplicationProperties["Name"] = "Test";
_logger.LogInformation("Final Sent Message Content-Type: {contentType}", serviceBusMessage.ContentType);
var sender = _serviceBusClient.CreateSender("kamtopic");
await sender.SendMessageAsync(serviceBusMessage);
await messageActions.CompleteMessageAsync(receivedMessage);
}
}
}
Output :
Azure Service Bus Topic :
I successfully set the contentType as application/json and Custom Properties under Message Properties in the Topic.
Upvotes: 0