In this article, we will explore the process of integrating Redis with .NET Aspire. As you may know, .NET Aspire is a powerful framework designed for building cloud-native applications.
This integration allows developers to leverage Redis’s high-performance in-memory data structure store, enhancing application speed and scalability. We will discuss the benefits of using Redis, the steps required for integration, and best practices to ensure optimal performance in your cloud-native applications.
Table of Contents
- What is Caching?
- Installing the necessary tools
- Create .Net Aspire Starter App
- Solution Explorer View of Project
- Adding Aspire.Hosting.Redis to App Host Project
- Adding Redis Resource
- Adding Insights extension
- Adding Redis Commander Extension
- Adding Data Volume Extension
- Adding WithDataBindMount Extension
- Adding WithPersistence Extension
- Add Redis client to APIService Project
- Adding Aspire.StackExchange.Redis.DistributedCaching NuGet package.
- Adding Swashbuckle.AspNetCore.SwaggerGen NuGet package.
- Adding Swashbuckle.AspNetCore.SwaggerUI NuGet package.
- Adding Model to API Service Project.
- UserDetailsModel Code Snippet
- Complete the Code Snippet of AspireApp2.AppHost Program.cs
- Complete the Code Snippet of AspireApp2.ApiService Program.cs
- Adding API Controller.
- Complete Code of API Controller
- ASPIRE Dashboard
- Swagger API documentation
- Call API Service for inserting data from POSTMAN
- Redis Commander
- Redis cache-insight
- Call API Service for Reading data.
What is Caching?
Caching is a way to keep important data in memory so that it can be accessed quickly. This means you don’t have to go back to the original source every time, which saves time.
In this section, we will explore the concepts of Distributed Cache and Output in detail.
Distributed cache –
Distributed caching is a type of caching that stores data across multiple servers. This allows the data to be shared between multiple instances of an application, which can help to improve scalability and performance.
Output Cache –
Output caching is a type of caching that stores the output of a web page or API response. This allows the response to be served directly from the cache rather than generating it from scratch each time. Output caching can help improve a web application’s performance by reducing the time it takes to generate a response.
Installing the necessary tools
To begin, we will create a .NET Aspire project. This process requires the installation of both .NET 9 and the .NET Aspire SDK.
For guidance on installing the necessary tools, please refer to the following link: [Installing Tools](https://learn.microsoft.com/en-us/dotnet/aspire/fundamentals/setup-tooling?tabs=windows&pivots=visual-studio).
Create .Net Aspire Starter App
I am currently utilizing Visual Studio 2022 for this demonstration. Let’s create a .NET Aspire project. To do this, we need to select the .NET Aspire Starter App Template. For your reference, please see the snapshot below.
After selecting the project, click the “Next” button to proceed.
A new dialog will appear, prompting you to configure your new project. Within this dialog, you will be asked to provide a Solution Name and specify the location where the project should be saved.
After entering details, click the “Next” button to proceed.
A new dialogue will appear, prompting you to configure additional information related to the project, such as the framework, the .NET Aspire version, and the option to create a test project. For this demonstration, I will select .NET Aspire 9.0.
Click on the Create button to create a project.
After creating a project, you will see the Solution Explorer, which displays the project based on the provided input. In a .NET Starter project, you will find four projects:
- API Service
- AppHost
- Service Default
- Web
ApiService:
A Minimal API project in ASP.NET Core that supplies data to the front-end application. It relies on the ServiceDefaults project for shared configurations.
AppHost:
Acts as the orchestrator project, responsible for integrating and configuring various components and services in the application. It should be set as the Startup project and depends on ApiService and Web.
ServiceDefaults:
A shared .NET project that handles reusable configurations for resilience, service discovery, and telemetry across the solution.
Web:
A Blazor App project built with ASP.NET Core, implementing default .NET Aspire service configurations. It depends on ServiceDefaults for shared settings.
Solution Explorer View of Project
We have created a solution, so let’s begin by adding Redis cache to the project.
You may be wondering which project we will be integrating Redis into and what we plan to implement.
Adding Aspire.Hosting.Redis to App Host Project
In the AppHost project, the first step is to install the Redis package and configure the service to ensure it is accessible for use by other services.
If Aspire.Hosting.Redis is already installed in your project, there is no need to install it again.
NuGet packages after adding to the project.
After installing the packages. Next, we need to add the service to the AppHost Project Program.cs class.
Adding Redis Resource
var builder = DistributedApplication.CreateBuilder(args);
// Added Redis resource
var cache = builder.AddRedis("cache");
var apiService = builder.AddProject<Projects.AspireApp2_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp2_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(cache)
.WaitFor(cache)
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();
Adding Insights Extension
To gain insights into Redis, you can enhance your experience by adding an extension.
// Added Redis resource
var cache = builder.AddRedis("cache")
.WithRedisInsight(); // Added Redis Insight
Adding Redis Commander Extension
Redis-Commander is a node.js web application used to view, edit, and manage a Redis Database.
// Added Redis resource
var cache = builder.AddRedis("cache")
.WithRedisInsight() // Added Redis Insight
.WithRedisCommander(); // Added Redis Commander Ui to Manage keys and values
Adding Data Volume Extension
We need to add data volume because as this project runs on a container if we don’t have persistence storage then data will get lost as the container restarts.
A data volume stores Redis data independently of the container’s lifecycle. It is mounted at /data in the Redis container, and if no name is specified, a random name is generated.
// Added Redis resource
var cache = builder.AddRedis("cache")
.WithRedisInsight() // Added Redis Insight
.WithRedisCommander() // Added Redis Commander Ui to Manage keys and values
.WithDataVolume(); // Adds a named volume for the data folder to a Redis container resource and enables Redis persistence.
Adding WithDataBindMount Extension
Adds a bind mount for the data folder to a Redis container resource and enables Redis persistence.
Data bind mounts use the host machine’s filesystem to keep Redis data persistent across container restarts. The mount point is C:\Redis\Data on Windows or /Redis/Data Unix systems.
// Added Redis resource
var cache = builder.AddRedis("cache")
.WithRedisInsight() // Added Redis Insight
.WithRedisCommander() // Added Redis Commander Ui to Manage keys and values
.WithDataVolume()// Adds a named volume for the data folder to a Redis container resource and enables Redis persistence.
.WithDataBindMount(
source: @"C:\RedisData\Data",
isReadOnly: false);
Adding WithPersistence Extension
Use the WithPersistence method to enable Redis data persistence with a data volume or bind mount.
// Added Redis resource
var cache = builder.AddRedis("cache")
.WithRedisInsight() // Added Redis Insight
.WithRedisCommander() // Added Redis Commander Ui to Manage keys and values
.WithDataVolume()// Adds a named volume for the data folder to a Redis container resource and enables Redis persistence.
//.WithDataBindMount(
// source: @"C:\RedisData\Data",
// isReadOnly: false)
.WithPersistence(
interval: TimeSpan.FromMinutes(5),
keysChangedThreshold: 100);
After exploring various options for data persistence with AppHost, the next step is to create an API within the APIService Project. This API will utilize Redis, which we have configured in the AppHost project, to store and retrieve data through API calls.
Add Redis client to APIService Project
Adding Aspire.StackExchange.Redis.DistributedCaching NuGet package.
After adding the NuGet package to the Project.
Next, we will integrate Swagger into this project to enhance our API documentation.
Adding Swashbuckle.AspNetCore.SwaggerGen NuGet package.
Adding Swashbuckle.AspNetCore.SwaggerUI NuGet package.
After adding the All NuGet package to the Project.
Adding Model to API Service Project.
UserDetailsModel Code Snippet
namespace AspireApp2.ApiService.Models;
public class UserDetailsModel
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
}
Now to AspireApp2.ApiService Project in the program.cs we are going to add the below services.
Complete the Code Snippet of AspireApp2.AppHost Program.cs
var builder = DistributedApplication.CreateBuilder(args);
// Added Redis resource
var cache = builder.AddRedis("cache")
.WithRedisInsight() // Added Redis Insight
.WithRedisCommander() // Added Redis Commander Ui to Manage keys and values
.WithDataVolume()// Adds a named volume for the data folder to a Redis container resource and enables Redis persistence.
//.WithDataBindMount(
// source: @"C:\RedisData\Data",
// isReadOnly: false)
.WithPersistence(
interval: TimeSpan.FromMinutes(5),
keysChangedThreshold: 100);
var apiService = builder.AddProject<Projects.AspireApp2_ApiService>("apiservice")
.WithReference(cache);
builder.AddProject<Projects.AspireApp2_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(cache)
.WaitFor(cache)
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();
Complete the Code Snippet of AspireApp2.ApiService Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.AddRedisDistributedCache(connectionName: "cache");
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Add service defaults & Aspire client integrations.
builder.AddServiceDefaults();
// added controller support
builder.Services.AddControllers();
// Add services to the container.
builder.Services.AddProblemDetails();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseExceptionHandler();
// added controller support
app.MapControllers();
app.UseSwagger();
app.UseSwaggerUI();
app.MapDefaultEndpoints();
app.Run();
After Completing with Configuration Next step we are going to Add the API Controller.
Adding API Controller.
Code of Adding Empty API Controller
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AspireApp2.ApiService
{
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
}
}
After adding the API controller, the next step is to implement methods for inserting data into the Redis cache and retrieving values from it. To achieve this, we will utilize the Microsoft extension for distributed caching. Additionally, we will employ constructor injection to obtain an instance of IDistributedCache.
Complete Code of API Controller
using AspireApp2.ApiService.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
namespace AspireApp2.ApiService
{
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IDistributedCache _cache;
/// <summary>
///
/// </summary>
/// <param name="cache"></param>
public UserController(IDistributedCache cache)
{
_cache = cache;
}
// GET api/<UserController>/5
[HttpGet("{id}")]
public UserDetailsModel? Get(string id)
{
string key = "User_" + id;
var userDetails = _cache.GetString(key);
if (userDetails != null)
{
return JsonSerializer.Deserialize<UserDetailsModel>(userDetails);
}
return null;
}
// POST api/<UserController>
[HttpPost]
public async Task<bool> Post([FromBody] UserDetailsModel userDetails)
{
string key = "User_" + Guid.NewGuid().ToString();
userDetails.Id = key;
string userdetails = JsonSerializer.Serialize(userDetails);
await _cache.SetStringAsync(key, userdetails);
return true;
}
}
}
After completing the integration with the API Service, we can proceed to run the application for the first time.
The Wow applications are currently operating within a Docker container.
This dashboard is designed for the ASPIRE project, where you can view all the applications that are running.
Aspire Dashboard
An application running in a docker container.
Swagger API documentation
Before inserting the document let’s have a view of API documentation.
Call API Service for inserting data from POSTMAN
Inserting Data into the cache for that we are going to call API Service.
To view the inserted data, we can utilize Redis Commander.
Redis Commander
Redis-Commander is a node.js web application used to view, edit, and manage a Redis Database.
To access the Redis Commander application, navigate to the Dashboard page and click on “Cache Commander.”
If you cannot view the data, please click the Refresh button to ensure the data becomes visible.
Redis cache-insight
To see cache-insight you can click on cache-insight name from Aspire Dashboard.
Call API Service for Reading data.
While reading data we need to pass user-id from URL as input.
I hope you find this article enjoyable. In this piece, we explored how to use Redis with Aspire and how to insert data into Redis. Additionally, we discussed the valuable insights Redis provides, which can be particularly beneficial in production environments when the load is significantly high.
GitHub Link :- https://github.com/saineshwar/Aspire_Redis
