azureLover
azureLover

Reputation: 75

Migration from Microsoft.Azure.ServiceBus to Azure.Messaging.ServiceBus

I'm trying to update this function to make use of Azure.Messaging.ServiceBus and drop Microsoft.Azure.ServiceBus altogether, however, I can't seem to find any resources for this. Anybody knows how to send a message to a topic using this package?

The older function is:

public async Task SendMessageToServiceBusTopic<T>(T request, string topicSubName, string submissionNumber)
{
    ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder =
        new ServiceBusConnectionStringBuilder(settings.ServiceBusConnectionString)
        {
            EntityPath = settings.ServiceBusTopic
        };
 
        TopicClient topicClient = new TopicClient(serviceBusConnectionStringBuilder);

        byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(request));
        await topicClient.SendAsync(new Message(bytes)
        {
            CorrelationId = context.CorrelationId,
            Label=topicSubName,
            UserProperties = { new KeyValuePair<string, object>("TrackingId", submissionNumber) }
        });          
}

So far I have managed:

Am i headed in the right direction?

public async Task SendMessageToServiceBusTopic<T>(T request, string topicSubName, string submissionNumber)
{
    ServiceBusClient client = new ServiceBusClient(settings.ServiceBusConnectionString);
    ServiceBusSender s = client.CreateSender(settings.ServiceBusTopic);

    byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(request));
    await s.SendMessageAsync(new ServiceBusMessage(bytes));
}

Upvotes: 5

Views: 5394

Answers (3)

moueidat
moueidat

Reputation: 564

I was in the same situation like you (trying to migrate to Azure.Messaging.ServiceBus which is now the recommended NuGet from Microsoft).

You can have a look at the migration guide from their Github to have an idea of how to make the transition smoother: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/MigrationGuide.md

/!\ IQueueClient and ITopicClient (both coming from Microsoft.Azure.ServiceBus) have been merged into a single object called ServiceBusSender.

Why ? to make our life easier ! Indeed, under the hood, ServiceBusSender now takes care of the process of sending the message, especially since a queue and a topic cannot have the same name if I'm not wrong.

Here's a sample code of mine to send a message using the new library:

    /// <summary>
    /// Send a message by serializing as JSON the object in input. 
    /// </summary>
    /// <param name="queueOrTopicName">Name of the queue or topic where the message will be sent.</param>
    /// <param name="messageToSend">Any C# object</param>
    /// <returns></returns>
    public async Task SendMessage(string queueOrTopicName, object messageToSend)
    {
        //ServiceBusSender should not be disposed (according to the documentation, Github, etc.)
        await using ServiceBusClient client = new ServiceBusClient(connectionString: "Your-ServiceBus-ConnectionString");
        await using ServiceBusSender sender = client.CreateSender(_queueOrTopicName);

        // create a message that we can send. UTF-8 encoding is used when providing a string.
        ServiceBusMessage message = BuildServiceBusMessage(messageToSend);

        // Finally send the message
        await sender.SendMessageAsync(message);
    }

    private ServiceBusMessage BuildServiceBusMessage<T>(T entity)
    {
        string serializedMessage = JsonConvert.SerializeObject(entity); // Still using Newtonsoft.Json but I don't see any obstacles of using System.Text.Json.
        ServiceBusMessage message = new ServiceBusMessage(serializedMessage)
        {
            MessageId = Guid.NewGuid().ToString(),
            ContentType = "application/json; charset=utf-8",
        };

        return message;
    }

If you have any needs to do Dependency Injection (to re-use the same ServiceBusClient object and avoiding instanciating ServiceBusClient for each message you want to send for example), you can refer to this stackoverflow that I discovered this week

How to register ServiceBusClient for dependency injection?

Upvotes: 2

Sean Feldman
Sean Feldman

Reputation: 25994

While you can construct a Service Bus Client each time, it's not ideal. Assuming you're using the latest In-Proc SDK, you can use one of these options:

[FunctionName("PublishToTopic")]
public static async Task Run(
    [TimerTrigger("0 */5 * * * *")] TimerInfo myTimer,
    [ServiceBus("<topic_name>", Connection = "<connection_name>")] IAsyncCollector<ServiceBusMessage> collector)
{
    await collector.AddAsync(new ServiceBusMessage(new BinaryData($"Message 1 added at: {DateTime.Now}")));
    await collector.AddAsync(new ServiceBusMessage(new BinaryData($"Message 2 added at: {DateTime.Now}")));
}

Alternatively,

[FunctionName("PublishWithSender"]
public static async Task Run(
    [TimerTrigger("0 */5 * * * *")] TimerInfo myTimer,
    [ServiceBus("<topic_name>", Connection = "<connection_name>")] ServiceBusSender sender)
{
    await sender.SendMessagesAsync(new[]
    {
        new ServiceBusMessage(new BinaryData($"Message 1 added at: {DateTime.Now}")),
        new ServiceBusMessage(new BinaryData($"Message 2 added at: {DateTime.Now}"))
    });
}

For Isolated Worker SDK it's somewhat different. See this post for details.

Upvotes: 1

Thiago Custodio
Thiago Custodio

Reputation: 18387

you're in the right direction. There's no easy migration tool/sample as they are different libraries dealing with the same service (Azure Service Bus).

Upvotes: 0

Related Questions