Introduction

Azure Service Bus is a messaging service provided by Microsoft Azure that allows communication between applications and services. It provides a reliable and scalable platform for sending and receiving messages asynchronously. Whether you're building a simple application or a complex distributed system, Azure Service Bus can help you decouple your components and scale your solutions.

Azure Service Bus

What We'll Cover?

In this article, we'll walk through the process of using Azure Service Bus. NET. We'll cover everything from creating a Service Bus instance in the Azure portal to sending and receiving messages using .NET APIs. Here's a brief overview of the topics we'll delve into.

Setting Up Azure Service Bus in the Azure Portal

Before we can start using Azure Service Bus to send and receive messages, we first need to create a Service Bus instance in the Azure portal.

Step 1. Go to the Azure Portal.

Open your preferred web browser and navigate to the Azure portal at portal.azure.com.

Step 2. Search for Service Bus.

In the search bar at the top, type "Service Bus" and select it from the list of available services.

Service Bus

Step 3. Click on the Create Button.

Once you're on the Service Bus page, click on the "Create" button to start configuring your Service Bus instance.

Create

Step 4. Provide Basic Details.

  1. Subscription: Choose the Azure subscription you want to use.
  2. Resource Group: Create a new resource group or select an existing one.
  3. Namespace: Enter a unique name for your Service Bus namespace.
  4. Location: Select the geographical region where you want your Service Bus to be deployed.
  5. Pricing Tier: Choose from Basic, Standard, or Premium tier based on your requirements.
    Namespace

Pricing Options

Before finalizing your Service Bus instance, it's essential to understand the pricing options available. Here's a detailed overview of the pricing plan.

Pricing Options

Step 5. Additional Options.

Advanced Tab

You can explore advanced options such as Minimum TTL Version and Local Authentication. For most cases, you can leave these as default settings.

Additional Options

Step 6. Networking.

Keep the default networking settings unless you have specific requirements.

Networking

Step 7. Review + Create.

Review the summary of all the details you've provided. Once you're satisfied, click on the "Create" button to create the Service Bus instance.

Review

Setting up queues within the Service Bus

Step 1. Select Queue from the Entity Menu.

In the Azure portal, navigate to your Service Bus instance. From the entity menu, choose "Queue."

Select Queue

Step 2. Click on New Queue.

Next, click on the "New Queue" button to create a new queue.

Step 3. Provide Queue Details.

Step 4. Create the Queue.

Once you've filled in the details, click on the "Create" button to create the queue.

Creating an API to Send Messages on the .NET Side

Create a New API Project

Start by creating a new API project in your preferred development environment.

Install Packages, Use the NuGet Package Manager to install the following packages.

Create a Controller for Sending Messages

Here I'm creating a new controller called "ServiceBusController". In this controller, I'm going to implement methods for sending messages to the service bus.

using API.Models;
using Azure.Messaging.ServiceBus;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace API.Controllers;

[Route("api/[controller]/[action]")]
[ApiController]
public class ServiceBusController : ControllerBase
{
    readonly IConfiguration _configuration; 

    public ServiceBusController(IConfiguration configuration)
    {
        _configuration = configuration; 
    }

    [HttpPost]
    public async Task<IActionResult> SendMessageAsync([FromBody] EmployeeModel employee)
    {
        string connectionString = _configuration.GetValue<string>("ServiceBusSettings:ConnectionString");
        string queueName = _configuration.GetValue<string>("ServiceBusSettings:QueueName");

        var client = new ServiceBusClient(connectionString);
        var sender = client.CreateSender(queueName);
        string body = JsonConvert.SerializeObject(employee);
        var message = new ServiceBusMessage(body);
        await sender.SendMessageAsync(message);
        return Ok("Message sent to the Service Bus queue successfully");
    } 
}
namespace API.Models;

public class EmployeeModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Designation { get; set; }
    public string Department { get; set; }
    public string Note { get; set; }
}

Explanation

Use Dependency Injection for Service Bus Client

We can also create instances of service bus clients using dependency injection. To enable this we first have to make changes in our program.cs file. Register Service Bus Client in your program.cs file by passing the connection string.


builder.Services.AddSingleton<ServiceBusClient>(
    new ServiceBusClient(builder.Configuration.GetValue<string>("ServiceBusSettings:ConnectionString"))
);

For using the Service Bus Client here I'm injecting it into the constructor. I'm also creating a sender in the constructor because I'm using a single queue in this whole controller. If you are going to use multiple queues you can follow a different approach.

using API.Models;
using Azure.Messaging.ServiceBus;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace API.Controllers;

[Route("api/[controller]/[action]")]
[ApiController]
public class ServiceBusController : ControllerBase
{
    readonly IConfiguration _configuration;
    readonly ServiceBusClient _serviceBusClient;
    private readonly ServiceBusSender _serviceBusSender;

    public ServiceBusController(IConfiguration configuration,
        ServiceBusClient serviceBusClient)
    {
        _configuration = configuration;
        _serviceBusClient = serviceBusClient;

        string queueName = _configuration.GetValue<string>("ServiceBusSettings:QueueName");
        _serviceBusSender = _serviceBusClient.CreateSender(queueName);
    } 
	
    [HttpPost]
    public async Task<IActionResult> SendMessageWithDIAsync([FromBody] EmployeeModel employee)
    {
        string body = JsonConvert.SerializeObject(employee);
        var message = new ServiceBusMessage(body);
        await _serviceBusSender.SendMessageAsync(message);
        return Ok("Message sent to the Service Bus queue successfully using dependency injection");
    }

}

Explanation

Scheduling Messages and Canceling Scheduled Messages

Scheduling Messages with Azure Service Bus

Azure Service Bus allows you to schedule messages to be delivered at a future time by specifying the ScheduledEnqueueTime property of the message. This feature provides flexibility in managing message delivery and enables you to design applications that cater to specific timing requirements.

Usage Scenarios

To schedule a message, you need to set the ScheduledEnqueueTime property of the message to the desired future time.

Here's how you can do it.



    [HttpPost]
    public async Task<IActionResult> ScheduleMessageAsync([FromBody] EmployeeModel employee)
    {
        string body = JsonConvert.SerializeObject(employee);
        var message = new ServiceBusMessage(body);

        // Schedule the message to be sent 5 minutes from now
        message.ScheduledEnqueueTime = DateTimeOffset.UtcNow.AddMinutes(5);

        // Schedule the message
        long sequenceNumber = await _serviceBusSender.ScheduleMessageAsync(message, message.ScheduledEnqueueTime);

        return Ok($"Message scheduled to the Service Bus queue successfully. Sequence number: {sequenceNumber}");
    }

Canceling Scheduled Messages

In addition to scheduling messages, Azure Service Bus also provides the capability to cancel scheduled messages if the need arises. This feature ensures that you maintain control over message delivery and can adjust schedules as required. If you need to cancel a scheduled message, you can do so by providing its sequence number. Here's how you can cancel a scheduled message


    [HttpPost]
    public async Task<IActionResult> CancelScheduledMessageAsync([FromQuery] long sequenceNumber)
    {
        // Cancel the scheduled message using its sequence number
        await _serviceBusSender.CancelScheduledMessageAsync(sequenceNumber);

        return Ok($"Scheduled message with sequence number {sequenceNumber} has been canceled.");
    }

Explanation

Creating an Azure Function to Receive Messages

Create a New Azure Function Project

Begin by creating a new Azure Function project in your development environment. You can use Visual Studio or Visual Studio Code for this.

 Function Project

Select Azure Service Bus Trigger

When creating a new function, choose the Azure Service Bus Queue Trigger option. This trigger will automatically execute your function whenever a new message arrives in the specified Service Bus queue.

Add Service Bus Connection Settings

In your Azure Function project, locate the local.settings.json file. This file contains configuration settings for your function.

Add the ServiceBusConnectionString and QueueName settings to this file. These settings will be used by the function to connect to your Service Bus instance and listen to the specified queue.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "ServiceBusConnectionString": "YOUR_SERVICE_BUS_CONNECTION_STRING",
    "QueueName": "YOUR_QUEUE_NAME"
  }
}

Implement the Function Logic

In your Azure Function project, locate the function file created by the Azure Function runtime. This file will have a name corresponding to the trigger type you selected (e.g., Function1.cs). Here i have renamed this function for this operation.

Implement the function logic to process incoming messages from the queue. This logic will be executed every time a new message arrives in the queue.

using Azure.Messaging.ServiceBus;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace ServiceBusReceiver;

public class TestQueueReceiver(ILogger<TestQueueReceiver> logger)
{
    [Function(nameof(TestQueueReceiver))]
    public async Task Run(
        [ServiceBusTrigger("%QueueName%", Connection = "ServiceBusConnectionString")] ServiceBusReceivedMessage message,
        ServiceBusMessageActions messageActions)
    {
        logger.LogInformation("Message ID: {id}", message.MessageId);
        logger.LogInformation("Message Body: {body}", message.Body);
        logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);

        // Complete the message
        await messageActions.CompleteMessageAsync(message);
    }
}

Explaination

Instead of solely logging the message body, consider

Output

Output

Conclusion

Azure Service Bus, coupled with .NET, offers a robust messaging solution for building scalable and resilient applications. By leveraging Service Bus queues and Azure Functions triggers, developers can seamlessly integrate asynchronous messaging into their applications, enabling efficient communication and workflow automation.

You can download and access source code from My GitHub. If you find this article helpful, kindly share it with your friends.