© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2023
A. Satapathi, A. MishraDeveloping Cloud-Native Solutions with Microsoft Azure and .NET https://doi.org/10.1007/978-1-4842-9004-0_2

2. Build a Web API to Send Messages to Azure Service Bus

Ashirwad Satapathi1   and Abhishek Mishra2
(1)
Gajapati, Odisha, India
(2)
Navi MUmbai, India
 

In the previous chapter, we briefly discussed key Azure services that are used to build resilient, scalable, and secure cloud native solutions. Many of these solutions leverage the power of message brokers to enable inter-application or service communication in an asynchronous manner. There are many such messaging systems available, including Apache Kafka, RabbitMQ, Azure Service Bus, ActiveMQ, and Amazon MQ. The focus of this chapter is to build decoupled solutions using Azure Service Bus, which is the enterprise-grade messaging solution offered by Microsoft Azure.

We will explore the key concepts and features of Azure Service Bus by building solutions using ASP.NET Core Web API for a fictional dental clinic to schedule appointment notifications for patients in a Service Bus Queue. The solution will be able to schedule a message for a future date as well as cancel it if the message has not been enqueued or has not been processed yet.

In this chapter, we will explore the following topics:
  • Introduction to Azure Service Bus

  • Features of Azure Service Bus

  • Getting started with Azure Service Bus: Queue and Topic

  • Provision an Azure Service Bus instance

  • Build an ASP.NET 6 Web API to send messages to Azure Service Bus Queue

After studying this chapter, you should have a solid grasp of the fundamentals of Azure Service Bus, as well as cloud services on Azure.

Introduction to Azure Service Bus

Enterprise messaging software, also known as message-oriented middleware, has been in existence since the late 1980s. Message-oriented middleware is a concept that involves the passing of data between applications using a communication channel that delivers messages from the sender to the receiver. These messages are transferred in an asynchronous manner between the sender and receiver using a message broker. These kinds of messaging systems help in decoupling applications and keeping the sender and receiver anonymous from each other. Azure Service Bus is one such messaging solution offered by Microsoft Azure as part of its cloud suite.

Azure Service Bus is an enterprise-grade, multitenant cloud messaging service of Microsoft Azure. It is a Platform-as-a-Service (PaaS) offering of Azure and is fully managed by Microsoft. As developers, we don’t need to worry about tasks such as handling of backups or hardware failures for the services because Azure takes care of it for us. Azure Service Bus supports point-to-point message delivery with Queues and message broadcasting using the publisher-subscriber model with Topics. In a later section of the chapter, we are going to briefly discuss Azure Service Bus Queues and Topics.

Azure Service Bus allows applications to interact or transfer data with each other using messages. It provides an excellent mechanism to build decoupled solutions and make them more scalable, reliable, and resilient. The producer should not be impacted due to the unavailability of the consumer. It supports data in different formats, such as JSON, XML, plain text, and so on, and provides client libraries in different languages to build solutions using it. Apart from that, it offers various advanced features such as message deferral, duplicate detection, and auto-forwarding, to name a few.

When to Use Azure Service Bus

There are various scenarios in which using Azure Service Bus would be appropriate and helpful for the overall function of our application as well as the architecture of the system. Some of them are listed here:
  • Increasing scalability of the application

  • Replacing RPCs

  • Integrating heterogeneous applications

  • Reducing the coupling between applications

There are many additional scenarios where Azure Service Bus can be handy to use. Let’s discuss how Service Bus can help in the case of heterogeneous applications.

Suppose we have two applications, Application A and Application B. Application A is written in Java while Application B is written in Python. To fulfill some requirements, we want to establish communication between these applications.

Normally, this would be really difficult to do between two applications written in different languages unless you have a common medium of communication between them.

Service Bus helps us do so without a lot of trouble. Service Bus provides clients for multiple languages, including .Net, Python, Ruby, and many more, which helps in sending messages between heterogeneous applications via its message broker.

Features of Azure Service Bus

The following are some of key features of Azure Service Bus:
  • Message filtering

  • Message sessions

  • Message auto-forwarding

  • Duplicate detection

  • Message expiration

  • Message deferral

  • Message batching

Let’s explore each of these features in detail.

Message Filtering

Azure Service Bus supports message filtering with Topics. It is supported with queues. You can configure subscription rules for Azure Service Bus Topics to deliver messages categorically to different subscribers as per the business requirements. A subscription rule can consist of filter condition or actions. To learn more about the message filtering feature of Azure Service Bus, take a look at https://docs.microsoft.com/en-us/azure/service-bus-messaging/topic-filters.

Message Sessions

Azure Service Bus provides a guaranteed reliable delivery of related messages in a particular sequence to the receiver/subscriber application by using message sessions. To leverage this feature, you will have to enable sessions while creating queues/topics. While sending a message to the queue/topic as part of a session, the sender application will also have to set the session ID property. This will help the receiver application to distinguish if a particular message is associated with a particular session or not. To learn more about message sessions of Azure Service Bus, check out https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sessions.

Message Auto-forwarding

Azure Service Bus provides a way to send messages from a particular queue or subscription to another queue or topic within the namespace for the purpose of chaining them. Any messages coming to our source queue/subscription will be removed and moved to the destination queue/topic automatically.

Duplicate Detection

In certain scenarios, a message sent by the sender application may not get delivered within a certain time period, because of which the sender application might resend the message to the service bus queue to be picked up by the receiver application for further processing. Now our receiver application will be processing the same message twice because of the message being resent by the sender. To remove such duplicate messages, Azure Service Bus provides a duplicate detection feature that discards the duplicate message for us.

Message Expiration

While solving real-world problems, we often come across scenarios where the time to live of a message is crucial for the sanity of the message. Some messages can be of no value after a certain threshold. For example, if a notification of an EMI payment to the customer is sent after the due date, it does not add any business value and may result in a bad customer experience. To avoid such scenarios, Azure Service Bus provides a feature to define the maximum time to live of messages for a queue or topic while we are provisioning them.

Message Deferral

Whenever you send a message to a message broker, it gets enqueued in a queue or topic and is available for the receiver application to pick up the message and process it further. But in some scenarios where you might want to schedule a message to be processed at a later date. Azure Service Bus provides a message deferral mechanism to address this scenario. You can schedule a message to be sent at a future date in the queue and the message will only get queued once the scheduled date has come. We are going on a use case for this feature and implement it later in the chapter.

Message Batching

Azure Service Bus provides a mechanism to batch a certain number of messages and send them in a batch to the receiver application to process at one go, which results in better utilization of resources at the receiver’s end.

Queues, Topics, and Namespaces

In this section, we are going to discuss the following key components of Azure Service Bus:
  • Queues

  • Topics

  • Namespaces

Queues

Azure Service Bus Queue enables applications to interact with each other using point-to-point messaging. In the point-to-point messaging style, we send messages in a synchronous as well as asynchronous manner using Queues. The message, sent by the sender application, is sent to the receiver application using the queue. Each message is delivered to the queue only once to a single receiver application. If a receiver is not available to process the message, the message stays in the queue until the configured time to live of the message expires.
Figure 2-1

Azure Service Bus Queue

Topics

Azure Service Bus Topics enables applications to interact with each other using the publisher-subscriber model. In the publisher-subscriber messaging style, sender applications are called publishers and receiver applications are called subscribers. Here, we use Topics to convey the messages among these sender and receiver applications. A topic can consist of multiple subscriptions. To receive messages, receiver applications need to subscribe to a subscription. Once receivers are registered to the subscription of the topic, every time a message is sent by the sender, all the receivers receive the messages.
Figure 2-2

Azure Service Bus Topic

Namespaces

In Azure Service Bus, Namespaces acts as a logical container for all the queues and topics. To create any queues or topics in Azure Service Bus, you first have to provision an Azure Service Bus Namespace. The number of queues or topics that you can have in a namespace is dependent on the pricing tier that you select while provisioning the namespace.

Working with Azure Service Bus

Now that you have a general understanding of what Azure Service Bus is and what are its key features and components, let’s create an Azure Service Bus Queue instance in Azure Portal, a simple message sender application, and a web API to schedule appointments for our fictional dental clinic.

Create an Azure Service Bus Namespace in Azure Portal

Go to the Microsoft Azure portal and search for Service Bus in the search box. Click Service Bus as shown in Figure 2-3.
Figure 2-3

Search for Service Bus

Click Create to provision a new Service Bus namespace, as shown in Figure 2-4.
Figure 2-4

Click Create

Select the Azure subscription and resource group name from the Subscription and Resource group drop-down lists, respectively, as shown in Figure 2-5. Then provide the namespace name, location, and pricing tier in the corresponding fields. The namespace name needs to be unique globally. After filling in all the required information, click Review + create.
Figure 2-5

Click Review + create

A validation check will be done in the current page with all the data that you have provided. If all the data is valid (see Figure 2-6), then you will be able to create the namespace. If there was any error, then the particular error will be highlighted in this screen. Once the validation is successful, click Create.
Figure 2-6

Click Create

You will be redirected to a page similar to Figure 2-7 that shows the status of the provisioning of your Service Bus namespace. Once the namespace has been created, click Go to resource.
Figure 2-7

Click Go to resource

Create an Azure Service Bus Namespace in Azure Portal

To create an Azure Service Queue inside your namespace, click + Queue as highlighted in Figure 2-8.
Figure 2-8

Click + Queue

To create the queue, you have to provide the queue name, as shown in Figure 2-9. The queue name needs to be unique inside a namespace. For purposes of this example, use the name myqueue. Keep the defaults for the Max queue size, Max delivery count, Message time to live, and Lock duration settings. The Message time to live configuration defines how long an unprocessed message stays in the queue, and the Lock duration configuration defines the time period during which the message is going to be unavailable in the queue. After the entering the details, click Create.
Figure 2-9

Click Create

This creates a Queue inside your Service Bus Namespace. You can view it by clicking Queues in the Entities section on the left side of the screen, as shown in Figure 2-10. You will see the list of all the queues present inside the namespace. Currently, you have just one queue, myqueue, as shown on the right in Figure 2-10.
Figure 2-10

View the list of queues

Create an SAS Policy to Access the Azure Service Bus Namespace

To access or interact with Azure Service Bus Queues or Topics from our application, we need to authenticate our application’s request to the service bus. This can be done in different ways, such as using Azure Active Directory (Azure AD)–based authentication or SAS policies. For the purpose of this book, we will be using SAS policies. For enterprise applications, it is recommended to use Azure AD–based authentication or managed identity if the applications are deployed inside Azure in an Azure Function or App Service by providing necessary role-based access control (RBAC) permissions to the service bus instance.

To create an SAS policy, click Shared access policies in the Settings section, as shown in Figure 2-11, and then click Add to add a new policy. Enter the policy name in the Policy name box on the right and define the scope of this policy. Following the principle to provide least privilege, click the Send check box to assign this policy only the ability to send messages to service bus queues or topics present inside our namespace, and then click Create.
Figure 2-11

Creating an SAS policy

Once the policy has been created, you need to fetch the primary connection string. We will be using this connection string later in this chapter to interact with Azure Service Bus Queue to send and schedule messages.
Figure 2-12

Getting the primary connection string

Create a Console App to Send Messages to Azure Service Bus Queue

Now that you have provisioned your Azure Service Bus Queue and have fetched the connection string, you are ready to start developing a console app to send messages to Service Bus Queue. Create a Console application project in the IDE of your choice and open the package manager console. Run the following command to install the Azure.Messaging.ServiceBus NuGet package:
Install-Package Azure.Messaging.ServiceBus
This is the Azure software development kit (SDK) for ServiceBus, which allows you to interact with Azure ServiceBus. Once the package has been installed, go to program.cs and add the following namespace:
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;
Next, create a variable to store the connection string from the SAS policy that you created in the previous section:
const string connectionString = "provide-your-connection-string";
Create a variable to store the queue name that you created earlier in the chapter:
const string queueName = "provide-your-queue-name";
Now that you have the connection string and queue name, create the service bus client instances that you need to send messages to the service bus:
static ServiceBusClient serviceBusClient = new ServiceBusClient(connectionString);
static ServiceBusSender serviceBusSender = serviceBusClient.CreateSender(queueName);
Replace the code present in the main method with the following code snippet, which creates an instance of ServiceBusBatchMessage to store ten messages and then uses the SendMessageAsync method of ServiceBusSender to send the messages to the service bus:
// create a batch
using ServiceBusMessageBatch messageBatch = await serviceBusSender.CreateMessageBatchAsync();
//Add 10 messages to the messageBatch
for (int i = 1; i <= 10; i++)
{
   // try to add a message to the batch
   if (!messageBatch.TryAddMessage(new ServiceBusMessage($"Message {i}")))
      {
          // if it is too large for the batch
          throw new Exception($"The message {i} is too large to fit in the batch.");
      }
 }
 // Use the serviceBusSender client to send the batch of messages to the Service Bus queue
 await serviceBusSender.SendMessagesAsync(messageBatch);
 Console.WriteLine($"A batch of 10 messages has been published to the queue.");
 Console.ReadLine();
// closing the connections and network resources
await serviceBusSender.DisposeAsync();
await serviceBusClient.DisposeAsync();
Listing 2-1 shows the complete code for the sender console application.
using Azure.Messaging.ServiceBus;
namespace ServiceBusConsole
{
    internal class Program
    {
        const string connectionString = "provide-your-connection-string";
        const string queueName = "provide-your-queue-name";
        // Creates the clients, we need to send messages to Azure Service Bus
        static ServiceBusClient serviceBusClient = new ServiceBusClient(connectionString);
        static ServiceBusSender serviceBusSender = serviceBusClient.CreateSender(queueName);
        static async Task Main()
        {
            // create a batch
            using ServiceBusMessageBatch messageBatch = await serviceBusSender.CreateMessageBatchAsync();
            for (int i = 1; i <= 10; i++)
            {
                // try adding a message to the batch
                if (!messageBatch.TryAddMessage(new ServiceBusMessage($"Message {i}")))
                {
                    // if it is too large for the batch
                    throw new Exception($"The message {i} is too large to fit in the batch.");
                }
            }
            // Use the producer client to send the batch of messages to the Service Bus queue
            await serviceBusSender.SendMessagesAsync(messageBatch);
            Console.WriteLine($"A batch of 10 messages has been published to the queue.");
            Console.ReadLine();
                // closing the connections and network resources
            await serviceBusSender.DisposeAsync();
            await serviceBusClient.DisposeAsync();
        }
    }
}
Listing 2-1

Program.cs

Now run your console app. Once the application has executed, go to the queue in the Azure portal. Figure 2-13 shows that ten messages were enqueued in the queue.
Figure 2-13

Ten messages were added to the queue

Create a Web API to Schedule Messages in Azure Service Bus Queue

In the previous section, you learned ways to send messages to the Azure Service Bus queue from your console application. This section focuses on solving the need of a fictional dental clinic to send appointment notifications to its patients. The dental clinic currently has a worker process in place that picks up messages from the service bus queue and processes them to send notifications. Currently, the worker process is processing any messages that are available in the queue, but the clinic doesn’t want the worker to send the notification until the right time. The notifications should be sent only three hours before the appointment time. Thus, the message cannot be sent to the queue directly. To solve this problem, we need to build a solution to schedule a message—an appointment reminder in this case—three hours before the appointment time so that the message enqueues in the queue at the scheduled time and then the worker process picks it up to process it and sends the notification to the patient.

We will be building an ASP.NET Core Web API to solve this problem by scheduling messages in the service bus queue by using the message deferral feature of Azure Service Bus. Our web API will provide two essential features: schedule a message to the service bus queue and cancel a scheduled message. There can be business scenarios where a patient can cancel a scheduled appointment and reschedule it for a future date. In such scenarios, the cancel feature will be essential, as we will have to cancel the existing scheduled message because it is no longer valid and may cause a bad customer experience.

As we have covered the business requirement, let’s start building our web API. Open Visual Studio 2022 and click Create a new project, as shown in Figure 2-14.
Figure 2-14

Creating a new project

Select the ASP.NET Core Web API project template, as shown in Figure 2-15, and click Next.
Figure 2-15

Click Next

Enter the project name, location, and solution name in the corresponding fields, as shown in Figure 2-16. Click Next to continue.
Figure 2-16

Enter the project name, location, and solution name

Now check the Use controllers check box, as we don’t want to use minimal APIs for the project, and keep the other options as shown in Figure 2-17. Click Create to create our web API project.
Figure 2-17

Click Create

Visual Studio will create a sample API project for us that contains a simple WeatherForecastController, which returns randomly generated weather data to the client. Remove the WeatherForecastController.cs and WeatherForecast.cs files from our project, because we don’t need them.

Open the Package Manager Console and run the following command to install the NuGet packages Azure.Messaging.ServiceBus, Microsoft.Extensions.Azure, and Newtonsoft.Json in our project. As discussed earlier in the chapter, Azure.Messaging.ServiceBus is used to communicate with Service Bus. Microsoft.Extensions.Azure is required to inject our Azure Clients inside our dependency container. Newtonsoft.Json will be used for serialization and deserialization of objects.
Install-Package Azure.Messaging.ServiceBus
Install-Package Microsoft.Extensions.Azure
Install-Package Newtonsoft.Json
Once you have installed the NuGet packages, go to the appsettings.json file of our project and add the following key/value pairs. We need to store the service bus connection string in ServiceBusConn, our queue name in queueName, and the duration before which the message should get scheduled in enqueueDifference.
"ServiceBusConn": "provide-your-connection-string",
"queueName": "provide-your-queue-name",
"enqueueDifference": -3
Open the program.cs file and the following namespace:
using Microsoft.Extensions.Azure;
Now, add the following code in program.cs to inject the service bus client in the dependency container of our project. We are using serviceBusConn stored in our appsettings.json file to create our ServiceBusClient.
builder.Services.AddAzureClients(
    client => client.AddServiceBusClient(builder.Configuration["serviceBusConn"])
    );

For the time being, we are done with the program.cs file of our project. Let’s create two folders in our project: Business and Models. The Business folder will contain our interface and the classes implementing them. The Models folder will contain the classes of our data models.

After creating both folders, create a class called Appointment.cs in the Models folder and paste the following code. This class represents the appointment data that we receive in the request payload. We have used data annotations to mark the necessary fields as required.
public class Appointment
    {
        [Required]
        public int AppointmentId { get; set; }
        [Required]
        public int PatientId { get; set; }
        [Required]
        public string? PatientName { get; set; }
        [Required]
        public string? PatientEmail { get; set; }
        [Required]
        public int CaretakerId { get; set; }
        [Required]
        public DateTime ScheduledAt { get; set; }
    }
Now that our model is ready, create an interface called INotificationBusiness.cs in the Business folder and add the method definitions. As you can see in the following code snippet, our interface contains two method definitions: ScheduleAppointmentNotification and CancelAppointmentNotification. The ScheduleAppointmentNotification method will be responsible for taking the appointment data coming from the request payload and scheduling it as a message for a future date in the service bus queue. The CancelAppointmentNotification method is responsible for canceling a scheduled message in the service queue. It takes the sequenceNumber as a parameter (i.e., messageSequenceNumber) and cancels the scheduled message.
public interface INotificationBusiness
    {
         public Task<long> ScheduleAppointmentNotification(Appointment appointment);
         public Task CancelAppointmentNotification(long id);
    }
Now that you know what each of the methods is designed to perform, create a class called NotificationBusiness.cs to implement the INotificationBusiness interface. Before implementing the interface, add the following properties:
public IConfiguration _configuration { get; set; }
public ServiceBusClient _serviceBusClient { get; set; }
public ServiceBusSender _serviceBusSender { get; set; }
Now, instantiate the properties by using constructor injection. Replace your constructor with the following code:
public NotificationBusiness(ServiceBusClient serviceBusClient, IConfiguration configuration)
        {
            _configuration = configuration;
            _serviceBusClient = serviceBusClient;
            _serviceBusSender = _serviceBusClient.CreateSender(_configuration.GetValue<String>("queueName"));
        }

In the preceding code snippet, we are leveraging the ServiceBusClient that we had injected in the DI container in our program.cs file and we are using it to instantiate the _serviceBusSender client to interact with the Azure Service Bus Queue whose name is stored with the key name as queueName in our appsetting.json file.

Now let’s implement the methods of the INotificationBusiness interface in the class. Let’s add the following code snippet to implement the methods.

The ScheduleAppointmentNotification converts the appointment object coming in the parameter of the method to a string type and then converts it into a service bus message. Then we calculate the time when we want to schedule it by subtracting three hours from the value passed in the ScheduledAt property of our appointment object in the parameter of our method and store it in the enqueueTime variable. It might be confusing at first glance when you see that enqueueTime will have three hours subtracted while we are using the AddHours method. It is happening as such because the value of enqueueDifference in our appsettings.json file is -3. We then use the ScheduleMessageAsync method of the ServiceBusSender client to schedule the message by passing our serviceBusMessage and enqueueTime as parameters. This method returns the sequence number of the scheduled message in the service bus queue.

Add the following code as the implementation for the ScheduleAppointmentNotification method in our NotificationBusiness class:
public async Task<long> ScheduleAppointmentNotification(Appointment appointment)
{
//Serialize the appointment object
String serializedContent = JsonConvert.SerializeObject(appointment);
//Create a service bus message which contains the serialized appointment data
ServiceBusMessage serviceBusMessage = new ServiceBusMessage(serializedContent);
var enqueueTime = appointment.ScheduledAt.AddHours(_configuration.GetValue<int>("enqueueDifference"));
//Schedules the message in the service bus queue
var messageSequenceNumber = await _serviceBusSender
            .ScheduleMessageAsync(serviceBusMessage, enqueueTime);
//Returns the message sequence number of the scheduled message in service bus queue
return messageSequenceNumber;
}

The CancelAppointmentNotification method takes a long value (i.e., messageSequenceNumber) as a parameter and then uses the CancelScheduledMessageAsync method of the serviceBusSender client to cancel the method.

Add the following code as the implementation for the CancelAppointmentNotification method in our NotificationBusiness class:
public async Task CancelAppointmentNotification(long messageSequenceNumber)
{
//Cancels a message
await _serviceBusSender.CancelScheduledMessageAsync(messageSequenceNumber);
}
As we have added the implementation of both the methods defined in our interface, let’s go to our program.cs file and add a singleton service in our DI container by adding the following code snippet:
builder.Services.AddSingleton<INotificationBusiness, NotificationBusiness>();
Now, let’s add an empty API controller called AppointmentController.cs in the controllers folder and then add the following constructor code in our controller to inject the NotificationBusiness object to our _notificationBusiness property using constructor dependency injection:
public INotificationBusiness _notificationBusiness { get; set; }
public AppointmentController(INotificationBusiness notificationBusiness)
        {
            _notificationBusiness = notificationBusiness;
        }

Let’s add our actions in our AppointmentController. We are going to have two actions: ScheduledAppointmentNotificationInQueue and CancelAppointmentNotificationFromQueue.

The purpose of the ScheduledAppointmentNotificationInQueue action is to schedule a message in our service bus queue. It makes a call to the ScheduleAppointmentNotification method of our NotificationBusiness class by passing the payload coming from the request body to complete the action.
  • URL route: http://localhost:5010/api/Appointment/Notification/schedule

  • HTTP verb: POST

Add the following code snippet to add the ScheduledAppointmentNotificationInQueue action in our controller:
[HttpPost("Notification/Schedule")]
public async Task<IActionResult> ScheduledAppointmentNotificationInQueue([FromBody] Appointment appointment)
{
    try
    {
        long msgSequenceNumber = await _notificationBusiness.ScheduleAppointmentNotification(appointment);
        return new OkObjectResult(new { MessageSequenceNumber = msgSequenceNumber });
    }
    catch (Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
    }
}
The purpose of the second action in our AppointmentController, CancelAppointmentNotificationFromQueue, is to cancel a scheduled message in the service bus queue by the using the messageSequenceNumber. It makes a call to the CancelAppointmentNotification method of our NotificationBusiness class by passing the messageSequenceNumber coming in the URL to compete this action.
  • URL route: http://localhost:5010/api/Appointment/Notification/Cancel/{messageSequenceNumber}

  • HTTP verb: DELETE

Add the following code snippet to add the CancelAppointmentNotificationFromQueue action in our controller:
[HttpDelete("Notification/Cancel/{messageSequenceNumber:long}")]
public async Task<IActionResult> CancelAppointmentNotificationFromQueue([FromRoute] int messageSequenceNumber)
{
    try
    {
        if (messageSequenceNumber < 0)
        {
            eturn new BadRequestObjectResult("Invalid value of messageSequenceNumber");
        }
        await _notificationBusiness.CancelAppointmentNotification(messageSequenceNumber);
        return new OkObjectResult("Scheduled message has been discarded.");
    }
    catch (Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
    }
}

And with this our API project to schedule notifications for our fictional dental clinic is complete. Press Ctrl+F5 to build and run our project. The complete source code of this API project can be found at the following GitHub repository: https://github.com/AshirwadSatapathi/DentalAppointments.

In the next section, we will test our API using Postman, which is an API testing tool.

Test APIs Using Postman

Now that we have developed our APIs and have run them locally, let’s perform a sanity test on the functionalities of our API. Let’s open Postman and create a collection for our requests. After creating the collection, add a request to test the ScheduledAppointmentNotificationInQueue API. Now define the request method as POST and define the route as http://localhost:5010/api/Appointment/Notification/schedule and then click the Body tab to add the appointment information in the payload in key/value pairs. After you add the preceding information, click Send to send a request to our API. The API will now receive a request, process this information, and schedule this message in the service bus queue. Once the message has been scheduled, it will return a 200 response code along with the messageSequenceNumber as shown in Figure 2-18.
Figure 2-18

Sending a request to schedule a message

We can now go to our queue in the service bus and see that a message has been scheduled, as shown in Figure 2-19.
Figure 2-19

A message has been scheduled in the service bus queue

Now that we have tested the ScheduledAppointmentNotificationInQueue API, let’s create a request in our collection to the CancelAppointmentNotificationFromQueue API. We will cancel the message that was scheduled as part of our test for the ScheduledAppointmentNotificationInQueue API. We will do this by passing the messageSequenceNumber of the scheduled message that was returned by our ScheduledAppointmentNotificationInQueue API as response i.e., 11. After creating a new request, define the request method as DELETE and define the API URL as http://localhost:5010/api/Appointment/Notification/Cancel/11. To test this API, just click Send and our CancelAppointmentNotificationFromQueue API will cancel the message and it won’t be able go to the queue anymore. Upon successful execution, our API would return 200 OK as the status code with the message Scheduled message has been discarded, as shown in Figure 2-20.
Figure 2-20

Sending a request to cancel a scheduled message

We can now go to our queue in the service bus and see that a message has been discarded and we have no scheduled message, as can be seen in Figure 2-21.
Figure 2-21

A scheduled message was discarded

Summary

Azure Service Bus is one of the most widely used cloud messaging services used by Microsoft Azure. It is a PaaS offering of Microsoft that helps us get rid of the hassles associated with infrastructure provisioning and maintenance of our messaging systems. Azure Service Bus provides rich support for SDKs in various languages like Node.js, Python .NET, Java, and forth. It supports protocols like Advanced Message Queuing Protocol (AMQP) and HTTPREST. It provides us two styles of messaging: point-to-point with Queues and publish-subscribe with Topics. In this chapter, you learned ways to provision an Azure Service Bus Namespace and Queue in Azure Portal. You learned how to develop a console app to send messages to the Azure Service Bus queue using a connection string. And finally, we built a set of APIs to schedule and cancel messages to solve the problem of our fictional dental clinic. During this process, you learned ways to leverage the Azure Service Bus SDK for .NET to build applications by implementing the message deferral feature of Service Bus.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset