Using Azure Service Bus Topics in Blazor Server

156 views Asked by At

I am trying to implement a message receiver in a Blazor Server web application.

The code for this operation is pretty straight forward.

  1. Inject a ServiceBusClient in the specific page.
  2. Create a Processor for a specific topic and subscription.
  3. Use the processor to connect the event handler for that subscription.

My goal with this implementation is that each client loading that specific page should receive the messages, but it isn't really working like that.

If two clients are loading the same page, one of them is getting the message. The next time a message is sent, it could be the other page that receives is.

Something tells me that this is due to the fact that the injected service is a singleton service and that it doesnt help that the message handler is connected twice.

I am not a specialist in this so this will be my best guess, but I was hoping that someone can guide me to do the proper implementation in order to get the desired result.

I have tried to retreive the service on the page inside a scope (using servicefactory but that doesnt work at all.

1

There are 1 answers

0
Sampath On

I have referred this MSDOC for Azure Service Bus client library for .NET Developers.

The ServiceBusClient, senders, receivers, and processors are safe to cache and use as a singleton for the lifetime of the application, which is best practice when messages are being sent or received regularly. They are responsible for the efficient management of network, CPU, and memory use, working to keep usage low during periods of inactivity.

These types are disposable and calling either DisposeAsync or CloseAsync is required to ensure that network resources and other unmanaged objects are properly cleaned up. It is important to note that when a ServiceBusClient instance is disposed, it will automatically close and clean up any senders, receivers, and processors that were created using it.

<!-- Pages/ServiceBus.razor -->
@page "/servicebus"
@using Azure.Messaging.ServiceBus

<h3>Service Bus Processor</h3>
<button @onclick="StartProcessing">Start Processing</button>

@if (receivedMessages.Any())
{
    <h4>Received Messages:</h4>
    <ul>
        @foreach (var message in receivedMessages)
        {
            <li>@message</li>
        }
    </ul>
}

@code {
    private ServiceBusProcessorService processorService;
    private ServiceBusProcessor processor;
    private List<string> receivedMessages = new List<string>();

    private async Task StartProcessing()
    {
        // Initialize your Service Bus
        string connectionString = "";
        string topicName = "sampathpujari";
        string subscriptionName = "sampathpujari";

        var retryOptions = new ServiceBusRetryOptions
            {
                Mode = ServiceBusRetryMode.Exponential,
                MaxRetries = 3,
                Delay = TimeSpan.FromSeconds(2),
                MaxDelay = TimeSpan.FromSeconds(30)
            };

        var serviceBusClient = new ServiceBusClient(connectionString, new ServiceBusClientOptions
            {
                RetryOptions = retryOptions
            });

        processorService = new ServiceBusProcessorService(serviceBusClient);
        processor = processorService.GetProcessorForTopicAndSubscription(topicName, subscriptionName);

        // Set up message handler
        processor.ProcessMessageAsync += ProcessMessages;

        // Set up error handler
        processor.ProcessErrorAsync += ErrorHandler;

        // Start processing
        await processor.StartProcessingAsync();
    }

    private async Task ProcessMessages(ProcessMessageEventArgs args)
    {
        // Your message handling logic
        var body = args.Message.Body.ToString();
        Console.WriteLine($"Received message: {body}");

        // Update the UI with the received message
        await InvokeAsync(() =>
        {
            receivedMessages.Add(body);
            StateHasChanged();
        });


        // Complete the message
        await args.CompleteMessageAsync(args.Message);
    }

    private Task ErrorHandler(ProcessErrorEventArgs args)
    {
        // Your error handling logic
        Console.WriteLine($"Error source: {args.Exception.Source}, Exception: {args.Exception.Message}");

        // Log the error or take appropriate action

        return Task.CompletedTask;
    }
}

// ServiceBusProcessorService.cs
using Azure.Messaging.ServiceBus;

public class ServiceBusProcessorService
{
    private readonly ServiceBusClient _serviceBusClient;

    public ServiceBusProcessorService(ServiceBusClient serviceBusClient)
    {
        _serviceBusClient = serviceBusClient;
    }

    public ServiceBusProcessor GetProcessorForTopicAndSubscription(string topicName, string subscriptionName)
    {
        return _serviceBusClient.CreateProcessor(topicName, subscriptionName);
    }
}


<!-- Pages/Index.razor -->
@page "/"

<h1>Hello, world!</h1>

<a href="/servicebus">Go to Service Bus</a>

enter image description here

enter image description here

  • Refer this SO to add Azure ServiceBusClient as singleton in .NETFramwork.