Using Redis Cache with ASP.NET Core 3.1 using StackExchange.Redis.Extensions.Core Extensions

In this article, we are going to learn how to Access Azure Redis cache using StackExchange.Redis.Extensions.Core Extensions.
StackExchange.Redis.Extensions.Core” Extensions are written by Ugo Lattanzi.

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 StackExchange.Redis.Extensions.Core, StackExchange.Redis.Extensions.AspNetCore, StackExchange.Redis.Extensions.Newtonsoft package from NuGet package.
  • Creating a Resource “Azure Cache for Redis” on Azure.
  • Getting access keys
  • Adding Access Keys to appsettings.json file
  • Adding “AddStackExchangeRedisExtensions” method in the ConfigureServices method
  • Adding DemoController and injecting IRedisCacheClient for accessing method.
  • Implementing AddAsync, AddAllAsync methods
  • Implementing GetAsync, GetAllAsync methods
  • Implementing RemoveAsync, RemoveAllAsync methods
  • Implementing ExistsAsync methods
  • Implementing SearchKeysAsync methods

Let’s start with creating an application.

Creating ASP.NET Core Application

Next, we are going to set Project Name “WebCacheStackExchangeDemo” 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 below package from NuGet Packages

  • StackExchange.Redis.Extensions.Core
  • StackExchange.Redis.Extensions.AspNetCore
  • StackExchange.Redis.Extensions.Newtonsoft

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.

"Redis": {
    "Password": "uefEg7DelBFFbAIw=",
    "AllowAdmin": true,
    "Ssl": true,
    "ConnectTimeout": 6000,
    "ConnectRetry": 2,
    "Database": 0,
    "Hosts": [
      {
        "Host": "CoreCacheDemo.redis.cache.windows.net",
        "Port": "6380"
      }
    ]
  }

appsettings.json file

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Redis": {
    "Password": "uefEg7DezCTgTJDnECMexdKqxTlg+NiWkRilBFFbAIw=",
    "AllowAdmin": true,
    "Ssl": true,
    "ConnectTimeout": 6000,
    "ConnectRetry": 2,
    "Database": 0,
    "Hosts": [
      {
        "Host": "CoreCache.redis.cache.windows.net",
        "Port": "6380"
      }
    ]
  }
}

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

Adding “AddStackExchangeRedisExtensions” method in the ConfigureServices method

In ConfigureServices Method first we are going to read Redis connection settings from appsettings.json file.

var redisConfiguration = Configuration.GetSection("Redis").Get<RedisConfiguration>();

After reading it we are going to pass values to AddStackExchangeRedisExtensions method as show below.

public void ConfigureServices(IServiceCollection services)
{
    var redisConfiguration = Configuration.GetSection("Redis").Get<RedisConfiguration>();
    services.AddControllersWithViews();
    services.AddStackExchangeRedisExtensions<NewtonsoftSerializer>(redisConfiguration);
}

After registering service next we are going add controller.

Adding DemoController and injecting IRedisCacheClient 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 IRedisCacheClient dependency.

using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }
        public IActionResult Index()
        {
            return View();
        }
    }
}

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

Adding Product Model for demo

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

Implementing AddAsync, AddAllAsync methods

AddAsync

Storing an object into Redis using AddAsync.
While storing, we are using “Db0” which is database 0, you can configure 16 different databases. To add, we are using AddAsync method.

  • Key
  • Object to store
  • DateTimeOffset
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using WebCacheStackExchangeDemo.Models;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            var product = new Product()
            {
                Id = 1,
                Name = "hand sanitizer",
                Price = 100
            };

            bool isAdded = await _redisCacheClient.Db0.AddAsync("Product", product, DateTimeOffset.Now.AddMinutes(10));

            return View();
        }
    }
}

Output

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

AddAllAsync methods

Storing multiple Object with single round trip.
We are storing a list of products with different keys in single go you can use this method to add keys to Redis in a single request.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using WebCacheStackExchangeDemo.Models;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {

            var values = new List<Tuple<string, Product>>
            {
                new Tuple<string, Product>("Product1", new Product()
                {
                    Id = 1,
                    Name = "hand sanitizer 1",
                    Price = 100
                }),
                new Tuple<string, Product>("Product2",new Product()
                {
                    Id = 2,
                    Name = "hand sanitizer 2",
                    Price = 200
                }),
                new Tuple<string, Product>("Product3", new Product()
                {
                    Id = 3,
                    Name = "hand sanitizer 3",
                    Price = 300
                })
            };

            await _redisCacheClient.Db0.AddAllAsync(values, DateTimeOffset.Now.AddMinutes(30));

            return View();
        }
    }
}

Output

Implementing GetAsync, GetAllAsync methods

GetAsync

GetAsync Retrieves an object which is stored in Redis.
Here we are going to Get stored product object from in Azure Redis cache. For getting it, we are going to use the GetAsync method and then we are going to pass key (‘Product’) to get Object.
Using the GetAsync method, we can get single objects or list of objects both we can get using the GetAsync method.

using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using System.Threading.Tasks;
using WebCacheStackExchangeDemo.Models;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            var productdata = await _redisCacheClient.Db0.GetAsync<Product>("Product");
            return View();
        }
    }
}

Object to retrieve

Output

GetAllAsync

Retrieves multiple Object with single round trip stored in Redis.
Here we are passing multiple keys and get all objects related to keys.

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using System.Threading.Tasks;
using WebCacheStackExchangeDemo.Models;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            List<string> allKeys = new List<string>()
            {
                "Product1","Product2","Product3"
            };

            var listofProducts = await _redisCacheClient.Db0.GetAllAsync<Product>(allKeys);
            return View();
        }
    }
}

Objects to retrieve

Output

Implementing RemoveAsync, RemoveAllAsync methods

RemoveAsync

Removing a single Object which is stored in Azure Redis cache.
Here just need to pass key “Product” to RemoveAsync method for removing Object.

using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using System.Threading.Tasks;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            bool isRemoved = await _redisCacheClient.Db0.RemoveAsync("Product");
            return View();
        }
    }
}

Object to remove

Output

RemoveAllAsync

Removing multiple Object which is stored Azure Redis cache with single round trip.
Here we are passing multiple keys to RemoveAllAsync method.

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using System.Threading.Tasks;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            List<string> allKeys = new List<string>()
            {
                "Product1",
                "Product2",
                "Product3"
            };

            await _redisCacheClient.Db0.RemoveAllAsync(allKeys);
            return View();
        }
    }
}

Objects to remove

Output

Implementing ExistsAsync methods

ExistsAsync method is used to check whether Object exists or not in Azure Redis Cache.
if object exists then ExistsAsync method will return true else false value.

using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using System.Threading.Tasks;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            bool isExists = await _redisCacheClient.Db0.ExistsAsync("Product");
            return View();
        }
    }
}

Objects

Output

Implementing SearchKeysAsync methods

SearchKeysAsync method is used to Search keys into Redis Cache.

  • If you want to search all keys that start with “Product*“.
  • If you want to search all keys that contain with “*Product*“.
  • If you want to search all keys that end with “*Product“.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis.Extensions.Core.Abstractions;
using System.Threading.Tasks;
using WebCacheStackExchangeDemo.Models;

namespace WebCacheStackExchangeDemo.Controllers
{
    public class DemoController : Controller
    {
        private readonly IRedisCacheClient _redisCacheClient;
        public DemoController(IRedisCacheClient redisCacheClient)
        {
            _redisCacheClient = redisCacheClient;
        }

        public async Task<IActionResult> Index()
        {
            // If you want to search all keys that start with 'Product*'
            var listofkeys1 = await _redisCacheClient.Db0.SearchKeysAsync("Product*");

            // If you want to search all keys that contain with '*Product*'
            var listofkeys2 = await _redisCacheClient.Db0.SearchKeysAsync("*Product*");

            // If you want to search all keys that end with '*Product'
            var listofkeys3 = await _redisCacheClient.Db0.SearchKeysAsync("*Product");

            return View();
        }
    }
}

Objects to search

Output

I hope you like it.

I try to make this article as simple as possible for beginners to understand it.

Thanks to Ugo Lattanzi for writing an extension for accessing Redis cache in ASP.NET CORE https://github.com/imperugo/StackExchange.Redis.Extensions.

By Saineshwar Bageri

I am Microsoft MVP | C# Corner MVP | Code Project MVP | FULL STACK .NET Developer and working on .Net Web Technology (Asp.net, Asp.net Core,.Net Core, C#, Sqlserver, MVC, Windows, Console Application, javascript, jquery, json, ORM Dapper) and also a freelance developer.