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!!


Bipin Joshi is an independent software consultant, trainer, author, and meditation teacher. He has been programming, meditating, and teaching for 24+ years. He conducts instructor-led online training courses in ASP.NET family of technologies for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get article updates : Facebook  Twitter  LinkedIn

Posted On : 02 September 2019


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates