In this article we will be exploring how to implement Azure Service bus with Asp.Net Core 5.
You can watch the entire video step by step on YouTube:
You can find the source code on GitHub:
https://github.com/mohamadlawand087/v14-AzureServiceBusWithAspNet5
So what are we going to cover today:
- What do we need to get started
- What are we going to build
- Azure Service bus basics
- The structure of our application
- Code
If you find this video helpful, please like, share and subscribe as it will really help the channel.
Before we start you will need to have
- Azure account (https://portal.azure.com)
- Dotnet SDK (https://dotnet.microsoft.com/download)
- Visual Studio Code (https://code.visualstudio.com/)
Links will be available in the description down below
So what are we going to build today, we will build a sample application which will contain a form which will collect data from the user and once that user submits the data we will want to send them an email confirming that we have received their information.
We will be covering Azure Service bus fundamentals, i have made a more in-depth video about Azure Service bus which you can find in the description and on the upper right hand corner.
In essence Azure Service Bus is a way to send a message from point a to point b. it means that i am going to put the info that i want to send somewhere and the specific service thats needs it will pick it up.
Azure Service bus leverage the idea of async process in the message queue and its very durable.
Once we publish a message to the queue its very hard to loose that data. So what is a message and what a queue
Message: Json Object which will contain all of the information that we need to send
Queue: a list of data items (Messages) stored to be retrievable in a definite order, usually the order of insertion (FIFO)
So how will the communication between our application and email service work. This is where message and queue comes into place.
When the web application collects its data from the user
- a message will be created
- that message will be sent on the service bus
- our email service will pick up that message
- and the mail service will send the email
We will be building 2 applications and 1 class-library, the first is an MVC application which will be responsible for sending the request, a console application which will be receiving it and outputting the results. The class-library will share classes between the projects for more reusable code.
We will start by creating an Asp.Net Core MVC application
dotnet new mvc -n "SampleWebSender" -lang "C#"
Class-library
dotnet new classlib -n "SampleShared"
Console Application
dotnet new console -n "SampleAppReceiver"
Once those applications are created we will need to add reference to the Class-library to the console application and the mvc project
dotnet add SampleWebSender/SampleWebSender.csproj reference SampleShared/SampleShared.csproj
dotnet add SampleAppReceiver/SampleAppReceiver.csproj reference SampleShared/SampleShared.csproj
The next step is to install some packages to our application, will start by installing packages to our MVC application, we will need to navigate to our application and install it
dotnet add package Microsoft.Azure.ServiceBus --version 5.1.1
We will need to do the same step for our console application, we will need to navigate to our application and install it
dotnet add package Microsoft.Azure.ServiceBus --version 5.1.
We will start by add model classes to our class library so inside our SampleShared library lets create a new folder called Model
Inside that folder will create a class called Person
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
Inside our MVC application we need to open the appsettings.json and add the ConnectionString section
"ConnectionStrings" : {
"AzureServiceBus" : ""
}
Inside our MVC application, we need to create a new folder called Services and will add to it a class and an interface called AzureBusService and IAzureBusService
public interface IAzureBusService
{
Task SendMessageAsync(Person serviceBusMessage, string queueName);
}
public class AzureBusService : IAzureBusService
{
private readonly IConfiguration _config;
public AzureBusService(IConfiguration config)
{
_config = config;
}
public async Task SendMessageAsync(Person serviceBusMessage, string queueName)
{
var queueClient = new QueueClient(_config.GetConnectionString("AzureServiceBus"), queueName);
// we convert the annonymous obj to a json
var msgBody = JsonSerializer.Serialize(serviceBusMessage);
var msg = new Message(Encoding.UTF8.GetBytes(msgBody));
await queueClient.SendAsync(msg);
}
}
Next step will be to go to our startup class and adding our service inside our ConfigureService method
services.AddTransient<IAzureBusService, AzureBusService>();
Now lets navigate to Azure and create a service bus
1- lets navigate to portal.azure.com
2- login or register if you don't have an account
3- Click on create resource
4- In the search bar type "Service bus"
5- Click on Service bus
6- Click on create
7- Choose a resource group name
8- Enter the Namespace name
9- Choose a location
10- Select Pricing tier: Basic
11- Click review and create
12- After it has been create will navigate to the resource group
13- Inside of our Service bus we need to go to Shared access policies
14- Will click on RootManageSharedAccessKey
15- in open tab lets copy the Primary connection string
Once we have the connection string lets go back to visual studio and will update our appsettings.json with the connection string
"ConnectionStrings" : {
"AzureServiceBus" : "Endpoint=sb://samplebus.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=VmU54+VIQaUp5P4Rl0y6No/eK85MhjjnhIY5Z86HYXw="
}
Now lets go back to Azure and go to our Service Bus resource, inside the resource we need to select Queues.
Click on + Queue and fill the form as follow,
- Name: MessageQueue
- Queue Size: 1G
- Max Delivery counts: 10 (if the lock duration is expired the message is unlocked and put back in the queue) if this happens 10 time it will go to the dead letter queue
- We don't change anything else and click on save
The queue is now created for us "MessageQueue"
Lets go back to VS code and open our HomeController inside the controllers folder
So inside our index action let's create the post action for Index which will be responsible for collection the information from the users and sending it to the Queue
private readonly ILogger<HomeController> _logger;
private readonly IAzureBusService _busService;
public HomeController(ILogger<HomeController> logger, IAzureBusService busService)
{
_logger = logger;
_busService = busService;
}
public IActionResult Index()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Index(Person person)
{
await _busService.SendMessageAsync<Person>(person, "emailqueue");
return RedirectToAction("Privacy");
}
Views
<form asp-action="Index" asp-controller="Home" method="POST">
<div class="row">
<div class="form-group">
<label>First Name:</label>
<input asp-for="FirstName" type="text" class="form-control required" placeholder="Enter First Name">
</div>
<div class="form-group">
<label>Last Name:</label>
<input asp-for="LastName" type="text" class="form-control required" placeholder="Enter Last Name">
</div>
<div class="form-group">
<label>Email:</label>
<input asp-for="Email" type="text" class="form-control required" placeholder="Enter Email">
</div>
</div>
<button type="submit" class="btn btn-succees">Save</button>
</form>
Now lets run the application and see if we are able to see the messages in Azure.
Next we will build our console app which will be responsible to receiving the message and sending the email, the email functionality we will be adding in a future video for now we will be just displaying the name and the email of the person
Console app
class Program
{
const string connectionString = "Endpoint=sb://samplebus.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=VmU54+VIQaUp5P4Rl0y6No/eK85MhjjnhIY5Z86HYXw=";
const string queueName = "emailqueue";
static IQueueClient queueClient;
static async Task Main(string[] args)
{
queueClient = new QueueClient(connectionString, queueName);
var msgHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
{
// hpw many messages we want to process at a time
MaxConcurrentCalls = 1,
// needs to wait until the message is processed not only read
AutoComplete = false
};
// register a method handler, this is the method that is going to be called when there is a new message
// this method will stay and run in the background
queueClient.RegisterMessageHandler(ProcessMessageAsync, msgHandlerOptions);
Console.ReadLine();
await queueClient.CloseAsync();
}
private static async Task ProcessMessageAsync(Message msg, CancellationToken token)
{
var jsonString = Encoding.UTF8.GetString(msg.Body);
var person = JsonSerializer.Deserialize<Person>(jsonString);
Console.WriteLine($"Email will be send to: {person.FirstName} {person.LastName} Email: {person.Email}");
// Email logic to be added
// Since in our options we have specified that the auto complete is false
// we need to tell the queue that its completed here
// we are taking the lock token and updating the queue that the message is completed
await queueClient.CompleteAsync(msg.SystemProperties.LockToken);
}
private static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs arg)
{
Console.WriteLine($"Message Handler Exception: {arg.Exception}");
return Task.CompletedTask;
}
}
Thank you for reading
Top comments (1)
Should the queueclient be created in the constructor? And how about disposing it?