Use Azure Cache for Redis in ASP.NET Core

Many ASP.NET Core application resort to caching for performance improvement
reasons. I have discussed a few caching techniques in
this,
this,
and this
article. Additionally developers also use
Azure Cache for Redis. It's a fully managed, high-performance in-memory
caching service that you can utilize in your ASP.NET Core web applications. This
article shows how.
The first step in using Azure Cache for Redis in your ASP.NET Core
application is to create a new cache by visiting Azure portal. To do that go to
Azure portal and locate Databases service.

From the list of database services pick Azure Cache for Redis. This will take
you to the main page of the service where you can add a new cache by clicking on
the Add button at the top.

In the New Redis Cache page enter details such as DNS name, Subscription, and
Resource Group. Also select a billing plan and click on Create to create the
cache. The DNS name is used to build a URI to the newly created cache. It might
take some time to get the cache created.
Once created locate the Access Keys option or click on Show Access Keys link
to revel the access keys. From this screen copy the Primary Connection String
and keep it ready to use in the ASP.NET Core app.

Next, create a new ASP.NET Core MVC web application as you normally do. Then
open appsettings.json file and add the following configuration to it.
"ConnectionStrings": {
"Northwind": "data source=.;
initial catalog=northwind;
integrated security=true",
"Redis": "YOUR_REDIS_PRIMARY_CONNECTION_STRING_HERE"
}
Here, you added ConnectionStrings section and stored two keys Northwind and
Redis. The Northwind key holds the database connection string to the Northwind
database whereas Redis key holds the Redis primary connection string that you
copied earlier. In this example you will cache employee details from Northwind
into Redis cache.
Now add these two NuGet package by right clicking Dependencies > Manage NuGet
Packages shortcut menu option:
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.Extensions.Caching.StackExchangeRedis
The Microsoft.EntityFrameworkCore.SqlServer package represents the EF Core
provider for SQL Server and is required to access data from Northwind database.
The Microsoft.Extensions.Caching.StackExchangeRedis is required to use Azure
Cache for Redis service.
Then open Startup class and add this code to ConfigureServices() method.
public void ConfigureServices(IServiceCollection
services)
{
services.AddControllersWithViews();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.
GetConnectionString("Northwind")));
services.AddStackExchangeRedisCache(option =>
{
option.Configuration =
Configuration.GetConnectionString("Redis");
});
}
The AddDbContext() method registers an EF Core DbContext class named
AppDbContext. You will create this class shortly. Moreover,
AddStackExchangeRedisCache() method registers types required by Azure cache for
Redis service. Inside this method you set the Configuration property to the
Redis connection string from the configuration file.
Next, add Employee entity class in the Models folder as shown below:
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Also add AppDbContext class as follows:
public class AppDbContext:DbContext
{
public AppDbContext(DbContextOptions
<AppDbContext> options) : base(options)
{
}
public DbSet<Employee> Employees { get; set; }
}
Now open HomeController and add a constructor as shown below:
public class HomeController : Controller
{
private IDistributedCache redisCache;
private AppDbContext db;
public HomeController(AppDbContext db,
IDistributedCache cache)
{
this.redisCache = cache;
this.db = db;
}
}
Above code declares two member variables in the HomeController - db and
redisCache. The constructor receives AppDbContext object and IDistributedCache
object. These objects are injected by DI container. Redis cache implements
IDistributedCache interface and is available as redisCache object.
Now that HomeController has received AppDbContext and IDistributedCache
object you can go ahead and apply
"cache-aside" pattern. Cache-aside pattern is quite simple and
straightforward. Here is how it works:
- First check for required data in the cache
- If the data is not there in the cache, connect with the database and
fetch the required data
- Store a copy of the data in cache
- Future requests for data are fulfilled from the cache (as long as data
exists in the cache)
Go to Index() action and write this code:
public IActionResult Index()
{
string jsonEmployees = redisCache.GetString
("employees");
if (jsonEmployees == null)
{
List<Employee> employees =
db.Employees.Take(9).ToList();
jsonEmployees = JsonSerializer.
Serialize<List<Employee>>(employees);
var options = new
DistributedCacheEntryOptions();
options.SetAbsoluteExpiration
(DateTimeOffset.Now.AddMinutes(1));
redisCache.SetString("employees",
jsonEmployees, options);
}
JsonSerializerOptions opt = new
JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
};
List<Employee> data = JsonSerializer.
Deserialize<List<Employee>>(jsonEmployees,opt);
return View(data);
}
Observe the code carefully. It begins by checking whether an item named
employees exists in the cache r not. This is done using GetString() method of
IDistributedCache object.
Initially this item won't be there in the cache and GetString() will return
null. The code inside the if block will get executed. This code fetches a List
of Employee objects using AppDbContext. This List is converted into its JSON
equivalent using Serialize() method of JsonSerializer class. The resultant JSON
string is put inside the cache using SetString() method. Notice that while
adding the employees item in the cache, its expiration is set to DateTimeOffset
value that is one minutes from now.
After the if block the code uses Deserialize() method of JsonSerializer to
construct a List object. Note that JsonSerializerOptions object specifies that
PropertyNameCaseInsensitive is true. The List is then passed to the Index view.
The Index view simply outputs the employees on the page.
@model List<Employee>
<h2>List of Employees</h2>
<table border="1" cellpadding="10">
@foreach (var emp in Model)
{
<tr>
<td>@emp.EmployeeID</td>
<td>@emp.FirstName</td>
<td>@emp.LastName</td>
</tr>
}
</table>
Here is a sample output:

In order to check whether caching of data is happening as expected or not,
run the application and quickly change Employees table data using SQL Server
Management Studio (or from Visual Studio). Then refresh the browser to see if
the changes are reflected. You will find that for one minute the changes aren't
reflected on the page indicating that data is cached for one minute.
That's it for now! Keep coding!!