Matthew Pieterse
Posted on September 25, 2024
A rapid-fire guide to integrating a custom Azure Queue Storage service class into your ASP.NET Web Application.
Connecting your Web Application
1) Install the official SDKs
Once you have created your ASP.NET Web application, you will need to install the official SDKs into your project from the NuGet package manager to access the Azure API.
dotnet add package Azure.Storage.Queues
2) Connect to your Azure Storage Account
If your packages were installed correctly, you can then proceed to add the connection string for your Azure storage account in your “appsettings.json” project file.
{
"ConnectionStrings": {
"AzureStorage": "connection-string"
}
}
As an important side-note, connection strings may contain sensitive information about your account, so it is recommended not to publish these directly into your production codebase!
Injecting your Services as Dependencies
1) Configure your project directories
The first step in this section is not strictly necessary but encourages good programming practices and will help you when following my other storage services in ASP.NET guides.
If you are interested in this, create your file and folder structure as follows in your project’s root directory. These services can also be separated into a class library for better organisation.
/- Services
*- QueueService.cs
*- QueueServiceFactory.cs
2) Create your services and factory classes
These are the classes that will be injected into your page models and controllers, and can be configured with the extension methods that you see fit for your application.
QueueService.cs
The queue service is constructed as an object instance and contains all of the extension methods that you will need to interact with your queue storage on Azure. The implementation below can be used to create queue containers directly from your codebase when a container with the specified name does not exist.
public sealed class QueueService
{
private readonly QueueClient _queueClient;
public QueueService(QueueServiceClient serviceClient, string container)
{
_queueClient = serviceClient.GetQueueClient(container.ToLower());
_queueClient.CreateIfNotExists(); // code-first queue creation
}
}
If you need granular control over your containers or a less error-prone implementation, modify the class to handle edge cases where the container specified in the parameter does not already exist.
public sealed class QueueService
{
private readonly QueueClient _queueClient;
public QueueService(QueueServiceClient serviceClient, string container)
{
_queueClient = serviceClient.GetQueueClient(container.ToLower());
if (!_queueClient.Exists()) {
// code to run if the container does not exist
}
}
}
QueueServiceFactory.cs
Factory classes simplify object creation. It will be used to create instances of the queue service that are linked to different containers on an as-needed basis, without having to connect the service to Azure each time.
public sealed class QueueServiceFactory(QueueServiceClient serviceClient)
{
public QueueService Create(string container)
=> new(serviceClient, container);
}
3) Registering your dependencies
ASP.NET Web applications all come with dependency injection services by default, but these can be manually installed from the NuGet package manager if this is not the case. I suggest researching the topic if you would like to learn more about how this works.
var builder = WebApplication.CreateBuilder(args);
var connect = builder.Configuration.GetConnectionString("AzureStorage");
builder.Services
.AddSingleton((x) => new QueueServiceClient(connect))
.AddScoped<QueueServiceFactory>();
Learn more about singleton and scoped service lifetimes from the official documentation.
Adding Operations to your Service
You can customise your service to include any extension method that you need, tailored completely to your project specifications. I have provided a few useful examples in the Gist for this article, and you can find some of the most commonly needed methods below.
Sending messages to the queue
public async Task SendToQueueAsync(string message)
{
await _queueClient.SendMessageAsync(message);
}
public async Task SendToQueueAsync(IEnumerable<string> messages)
{
var queue = new List<string>(messages);
foreach (var message in queue) {
await _queueClient.SendMessageAsync(message);
}
}
View messages in the queue without changing visibility
public async Task<IEnumerable<PeekedMessage>> FetchAllIncognitoAsync()
{
var queue = await _queueClient.PeekMessagesAsync(maxMessages: 32);
return new List<PeekedMessage>(queue);
}
public async Task<PeekedMessage> FetchOneIncognitoAsync()
{
var message = await _queueClient.PeekMessageAsync();
return message;
}
Fetch and then remove messages in the queue
public async Task<IEnumerable<QueueMessage>> FetchAllAsync()
{
var queue = await _queueClient.ReceiveMessagesAsync(maxMessages: 32);
return new List<QueueMessage>(queue);
}
public async Task<QueueMessage> FetchOneAsync()
{
var message = await _queueClient.ReceiveMessageAsync();
return message;
}
Clear all messages in the queue
public async Task ClearAll()
{
await _queueClient.ClearMessagesAsync();
}
Using your Queue Service
Your newly created queue service can be used anywhere you need in your application just by adding the factory class in the parameters of your constructors.
Code explanation
- The queue service factory is automatically injected into the parameters of the page model when it is created.
- The factory is used to create several instances of the queue service that are each associated with different queues/containers. The desired container is specified when creating the object.
public class Index(QueueServiceFactory queueFactory) : PageModel
{
private readonly QueueService _queueOrders
= queueFactory.Create("queue-container");
private readonly QueueService _queueLogger
= queueFactory.Create("queue-container");
}
Thanks for reading!
If you have any suggestions or questions about this article, please leave a comment below for me to get back to! I am a student, and your feedback helps me and the aspiring .NET community at large.
I became inspired to write this article during a coffee-fueled flow while working on a crucial assignment. After struggling to find useful articles on the topic, Darshana Mihiran Edirisinghe came to the rescue with his article linked below. I have adapted his teachings for a use case that I felt wasn’t covered, but this would not be possible without his work.
The public Gist containing the example source code used in this article can be found on my personal GitHub profile.
Posted on September 25, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.