Queue Storage in ASP.NET [Azure]

Matthew Pieterse - Sep 25 - - Dev Community

A rapid-fire guide to integrating a custom Azure Queue Storage service class into your ASP.NET Web Application.

Image of a tower


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
Enter fullscreen mode Exit fullscreen mode

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"
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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>();
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

Clear all messages in the queue

public async Task ClearAll() 
{
    await _queueClient.ClearMessagesAsync();
}
Enter fullscreen mode Exit fullscreen mode

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");
}
Enter fullscreen mode Exit fullscreen mode

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.

[Embedded Article]

The public Gist containing the example source code used in this article can be found on my personal GitHub profile.

.
Terabox Video Player