Using Distributed Redis Cache with ASP.NET Core 3.1

In this article, we are going to learn how to Use Redis cache with ASP.NET Core using the package “Microsoft.Extensions.Caching.Redis” provided by Microsoft.
The Cache is used to cache data which is frequently used and which does not change often.

Let’s take a scenario.

If you have large application and role wise menus stored in the Database which are shown to the user as they login these menus does not change frequently, meanwhile think if the number of users accessing the application at once are in thousands each time you will hit the Database to get data you which will create unusual load on SQL database for getting static data. Its is better to store all menus data in the Cache and set an expiry date to it. Another way will be you can add new menu store it in the Database and then load all menus into the Cache. Now whenever a user will access the menu, he will hit Cache not database this will help you reduce hits on Database.

We are going to use “Azure Cache for Redis” to store and retrieve data from the Cache.

Azure Cache for Redis provides you access to a secure, dedicated Redis cache. Azure Cache for Redis is managed by Microsoft, hosted within Azure, and accessible to any application within or outside of Azure.

  • Creating application ASP.NET Core Application
  • Installing Microsoft.Extensions.Caching.Redis package from NuGet package.
  • Creating a Resource “Azure Cache for Redis” on Azure.
  • Getting access keys
  • Adding Access Keys to appsettings.json file
  • Adding “AddDistributedRedisCache” method in the ConfigureServices method
  • Adding DemoController and injecting IDistributedCache for accessing method.
  • Implementing Set, SetAsync, SetString ,SetStringAsync methods
  • Using RedisDesktopManager to View stored Cache on Azure
  • Implementing Get, GetAsync, GetString, GetStringAsync methods
  • Implementing Remove, RemoveAsync methods
  • Implementing Refresh, RefreshAsync methods

Let’s start with creating an application.

Creating ASP.NET Core Application

Next, we are going to set Project Name “WebCacheDemo” and location. In last part, we are going to choose .Net Core framework and ASP.NET Core Version 3.1 as the framework for application and few advance settings for such as configuring https and enabling docker we are not going to enable docker settings for this project.

Now finally click on create button to create a project.

Project structure
The project structure generated according to the configuration.

After creating project next, we are going to install Microsoft.Extensions.Caching.Redis package from NuGet Packages.

Installing Microsoft.Extensions.Caching.Redis package from NuGet package

For installing AutoMapper right click on a project select Manage NuGet Packages and then search “Microsoft.Extensions.Caching.Redis” and click on the install button.

Creating a Resource “Azure Cache for Redis” on Azure

We are going to Create a Resource “Azure Cache for Redis” on Azure.
After login into azure portal and click on Create Resource below view is displayed.

Now from azure Marketplace, we are going to choose Database.

After choosing Database, we are going to select “Azure Cache for Redis“.

After selecting Azure Cache for Redis, we are going to see Create screen of Redis cache.
In this Screen, we are going to set DNS name as “CoreCache” and location whichever is right for you for this demo I am going to choose “Central India” location also we are going to take basic tier “Basic C0“.

After configuring settings next, we are going to click on the Create button to create a Cache. This process will take a bit of time, but you can monitor the status of it. If your status as running means you Redis cache is ready to use.

After deployment of Redis is successful next, we are going to get Access keys to access Redis Resource form C#.

Getting Access keys

Here we are going to click on Resource which we have created “CoreCache” in Settings you will find Access keys.

Next, we are going set connection string in appsettings.json file. For that, we are going to use Primary connection string from Access Keys.

"RedisCache": {
    "ConnectionString": " CoreCache.redis.cache.windows.net:6380,password=#######=,ssl=True,abortConnect=False"
  }

appsettings.json file

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "RedisCache": {
    "ConnectionString": "CoreCache.redis.cache.windows.net:6380,password=#####=,ssl=True,abortConnect=False"
  }
}

After setting connection string in appsettings.json file next, we are going register “AddDistributedRedisCache” service in ConfigureServices Method.

Adding “AddDistributedRedisCache” method in the ConfigureServices method

While registering service we are going set “Configuration” property of AddDistributedRedisCache method here we are going to pass “RedisCache:ConnectionString” connection string.

AddDistributedRedisCache Adds Redis distributed caching services to the specified IServiceCollection.
RedisCacheOptions has configuration property which is used to connect to Redis.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddDistributedRedisCache(option =>
    {
        option.Configuration = Configuration["RedisCache:ConnectionString"];
    });
}

After registering service next we are going add a controller.

Adding DemoController and injecting IDistributedCache for accessing method

We are going to add a controller with name DemoController after adding we are going to add a constructor to it. For injecting IDistributedCache dependency.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public IActionResult Index()
        {
            return View();
        }
    }
}

After creating a controller and adding constructor of class for injecting dependency next we are going to implement methods of it.


Implementing Set, SetAsync, SetString ,SetStringAsync methods

For a demo to add data to Cache, we are going to create a class product which will have 3 properties init.

namespace WebCacheDemo.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }
    }
}

Absolute Expiration
the Cache will be expired after a particular time irrespective of the fact whether it has been used or not in that time span.
Sliding Time Expiration
the Cache will be expired after a particular time only if it has not been used during that time span.
AbsoluteExpirationRelativeToNow
The cache work similar to Absolute Expiration.

1. Set method

In Set, a method takes 3 parameters

  • Key
  • Value in bytes
  • DistributedCacheEntryOptions

If you see below source code first, we have created an object of product class then we have serialized it then we are getting bytes of a serialized object and finally pass bytes to Set method.

Set method first parameter is key which is a unique name for Cache. The second parameter we are going to pass is data which is in bytes, and the last parameter is DistributedCacheEntryOptions in this we option we are going to set expiration time (AbsoluteExpiration) for Cache.

public IActionResult Index()
 {
     // Step 1 
     Product product = new Product()
     {
         Id =1,
         Name ="Pendrive",
         Price = 300
     };

     // Step 2 
     string serializeObject = JsonConvert.SerializeObject(product);
     // Step 3
     byte[] data = Encoding.UTF8.GetBytes(serializeObject);
     // Step 4
     _distributedCache.Set("product", data, new DistributedCacheEntryOptions()
     {
         AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5)
     });

     return View();
 }

Which object will be injected at runtime?

Implementation of AddDistributedRedisCache Service.

After setting values next let’s run application and access /Demo/Index URL to add some values to Azure Redis Cache.
This is an object which is converted into bytes and stored into Cache.

I previously was using Redis Desktop Manager to see key and values which are stored in Redis. But now the Redis Desktop Manager tool is not free. You can use another free tool AnotherRedisDesktopManager that has cool features.

Download Another-Redis-Desktop-Manager.1.4.3.exe

It is easy to use a tool just click on connect to Redis server enter your azure Address (Hostname) and Auth (Primary key) just click on test connection button to check entered values are proper and if it is successful then click ok button to see all keys and values stored in Redis Cache Server.

2. SetAsync method

Asynchronously sets a sequence of bytes in the specified Cache with the specified key.
It is the asynchronous version of the Set method. The method is marked with the async keyword, which tells the compiler to generate callbacks for parts of the body and to automatically create a Task that is returned. We also have applied await keyword to SetAsync method. The await keyword does not block the thread until the task is complete.

In SetAsync method take 3 parameters

  1. Key
  2. Value in bytes
  3. DistributedCacheEntryOptions
public async Task<IActionResult> Index()
{
    Product product = new Product()
    {
        Id = 1,
        Name = "Pendrive",
        Price = 300
    };

    // Step 2 
    string serializeObject = JsonConvert.SerializeObject(product);
    // Step 3
    byte[] data = Encoding.UTF8.GetBytes(serializeObject);
    // Step 4
    await _distributedCache.SetAsync("product", data, new DistributedCacheEntryOptions()
    {
        AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5)
    });
    return View();
}

3. SetString method

Sets a string in the specified Cache with the specified key.

In SetString method take 3 parameters

  1. Key
  2. Value in string
  3. DistributedCacheEntryOptions
public IActionResult Index()
 {
     // Step 1 
     Product product = new Product()
     {
         Id =1,
         Name ="Pendrive",
         Price = 300
     };

     // Step 2 
     string serializeObject = JsonConvert.SerializeObject(product);

     // Step 3
     _distributedCache.SetString("product_ SetString", serializeObject, new DistributedCacheEntryOptions()
     {
         AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5)
     });

     return View();
 }

After setting values next let’s run application and access /Demo/Index URL to add some values to Azure Redis Cache.
An object is going to store in Azure Cache.

4. SetStringAsync method

Asynchronously sets a string in the specified Cache with the specified key.
It is the asynchronous version of the SetString method. The method is marked with the async keyword, which tells the compiler to generate callbacks for parts of the body and to automatically create a Task that is returned. We also have applied await keyword to SetStringAsync method.

The await keyword does not block the thread until the task is complete.

In SetString method take 3 parameters

  1. Key
  2. Value in string
  3. DistributedCacheEntryOptions
public async Task<IActionResult> Index()
{
    // Step 1 
    Product product = new Product()
    {
        Id = 1,
        Name = "Mouse",
        Price = 500
    };

    // Step 2 
    string serializeObject = JsonConvert.SerializeObject(product);

    // Step 3
    await _distributedCache.SetStringAsync("product_SetString", serializeObject, new DistributedCacheEntryOptions()
    {
        AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5)
    });

    return View();
}

Till now we have stored values it Caches now we are going to read Values which are stored in it.


Implementing Get, GetAsync, GetString GetStringAsync methods

1. Get method

Gets a value with the given key.

In this part, we are going to get values stored in Azure Redis cache using Get Method.
We are using Get Method it will return bytes to us which we are going to convert to string and then Deserialize to Product type which will be the value which we are going to get from Azure Redis cache which we have stored.

using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using WebCacheDemo.Models;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public IActionResult Index()
        {
            var product = _distributedCache.Get("product");
            var bytesAsString = Encoding.UTF8.GetString(product);
            var deserializeObject = JsonConvert.DeserializeObject<Product>(bytesAsString);
            return View();
        }
    }
}

2. GetAsync method

Gets a value with the given key in an asynchronous way.

It is similar to Get Method just we need to pass key it will return bytes which we are going to convert to string and then Deserialize to Product type which will be the value which we are going to get from Azure Redis cache which we have stored.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System;
using System.Text;
using System.Threading.Tasks;
using WebCacheDemo.Models;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public async Task<IActionResult> Index()
        {
            var product = await _distributedCache.GetAsync("product");
            if (product == null) throw new ArgumentNullException(nameof(product));
            var bytesAsString = Encoding.UTF8.GetString(product);
            var deserializeObject = JsonConvert.DeserializeObject<Product>(bytesAsString);
            return View();
        }
    }
}

Output in Debug Mode

3. GetString method

Gets a string from the specified Cache with the specified key. This method will return the string we just need to deserialize it to specific type which we require.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using WebCacheDemo.Models;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public IActionResult Index()
        {
            var product = _distributedCache.GetString("product");
            var deserializeObject = JsonConvert.DeserializeObject<Product>(product);
            return View();
        }
    }
}

4. GetStringAsync method

Asynchronously gets a string from the specified Cache with the specified key.
It is similar to GetString Method just we need to pass key it will return string we just need to deserialize it to specific type which we require.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System.Threading.Tasks;
using WebCacheDemo.Models;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public async Task<IActionResult> Index()
        {
            var product = await _distributedCache.GetStringAsync("product");
            var deserializeObject = JsonConvert.DeserializeObject<Product>(product);
            return View();
        }
    }
}

After completing with Get method next, we are going to learn how to remove Cache from Azure Redis Cache.


Implementing Remove, RemoveAsync methods

Removes the value with the given key.

1. Remove

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public IActionResult Index()
        {
              _distributedCache.Remove("product");
              return View();
        }
    }
}

2. RemoveAsync

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public async Task<IActionResult> Index()
        {
            await _distributedCache.RemoveAsync("product");
            return View();
        }
    }
}

Implementing Refresh, RefreshAsync methods

Refreshes a value in the Cache based on its key, resetting its sliding expiration timeout.

Here I am setting Cache with key name “product” and we are going to set 2 expiration to it one I AbsoluteExpiration and another is SlidingExpiration.

1. Refresh

public IActionResult Index()
 {
     // Step 1 
     Product product = new Product()
     {
         Id = 1,
         Name = "Pendrive",
         Price = 300
     };

     // Step 2 
     string serializeObject = JsonConvert.SerializeObject(product);
     // Step 3
     byte[] data = Encoding.UTF8.GetBytes(serializeObject);
     // Step 4
     _distributedCache.Set("product", data, new DistributedCacheEntryOptions()
     {
         AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(4),
         SlidingExpiration = TimeSpan.FromMinutes(1)
     });
     return View();
 }

2. RefreshAsync

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using System.Threading.Tasks;

namespace WebCacheDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IDistributedCache _distributedCache;
        public DemoController(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        public async Task<IActionResult> Index()
        {
            await _distributedCache.RefreshAsync("product");
            return View();
        }
    }
}

In this article, we have learned how to Use Redis Cache with ASP.NET Core Using Microsoft.Extensions.Caching.Redis package in details. Hope you liked it.

By