Redis with .NET
In order to use Redis with .NET, you need a .NET Redis client. This article shows how to use StackExchange.Redis, a general purpose Redis client. More .NET Redis clients can be found in the C# section of the Redis Clients page.
Install StackExchange.Redis
There are several ways to install this package including:
- With the .NET CLI:
dotnet add package StackExchange.Redis
- With the package manager console:
PM> Install-Package StackExchange.Redis
- With the NuGet GUI in Visual Studio
Connect to Redis
The following code creates a connection to Redis using StackExchange.Redis in the context of a console application:
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
namespace ReferenceConsoleRedisApp
{
class Program
{
static readonly ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(
new ConfigurationOptions{
EndPoints = { "redis-12000.cluster.redis.com:12000" },
});
static async Task Main(string[] args)
{
var db = redis.GetDatabase();
var pong = await db.PingAsync();
Console.WriteLine(pong);
}
}
}
The above example assumes that you have a Redis Server running locally.
To configure the connection to your environment, adjust the parameters in the ConfigurationOptions object appropriately. For the remainder of the examples, the configuration uses localhost
.
Connection pooling
StackExchange.Redis does not support conventional connection pooling. As an alternative solution, you can share and reuse the ConnectionMultiplexer
object.
Do not create a separate ConnectionMultiplexer
for each operation. Instead, create an instance at the beginning and then reuse the object throughout your process.
ConnectionMultiplexer
is thread-safe, so it can be safely shared between threads. For more information, see the Basic Usage.
Dependency injection of the ConnectionMultiplexer
As the ConnectionMultiplexer
must be shared and reused within a runtime, it’s recommended that you use dependency injection to pass it where it’s needed. There’s a few flavors of dependency injection depending on what you’re using.
ASP.NET Core
A single ConnectionMultiplexer
instance should be shared throughout the runtime.
Use the AddSingleton
method of IServiceCollection
to inject your instance as a dependency in ASP.NET Core when configuring your app’s services in Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
//Configure other services up here
var multiplexer = ConnectionMultiplexer.Connect("localhost");
services.AddSingleton<IConnectionMultiplexer>(multiplexer);
}
Once the service is registered, you can inject it into anything that allows dependency injection, such as MVC Controllers, API Controllers, Blazor Server Components, and more.
The following code shows how to pass the service to a RedisController
instance:
[Route("api/[controller]")]
[ApiController]
public class RedisController : ControllerBase
{
private readonly IConnectionMultiplexer _redis;
public RedisController(IConnectionMultiplexer redis)
{
_redis = redis;
}
[HttpGet("foo")]
public async Task<IActionResult> Foo()
{
var db = _redis.GetDatabase();
var foo = await db.StringGetAsync("foo");
return Ok(foo.ToString());
}
}
Azure Functions
There are two types of Azure Functions to consider: in-process and out-of-process. Both handle dependency injection differently.
In-process Azure Functions
In-process Azure Functions handle dependency injection similarly to ASP.NET Core.
To use dependency injection, follow these steps:
- Create a
Startup.cs
file - Extend
FunctionsStartup
- Override the
Configure
method - Add the multiplexer as a singleton service for the function.
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var muxer = ConnectionMultiplexer.Connect("localhost");
builder.Services.AddSingleton<IConnectionMultiplexer>(muxer);
}
}
}
Out-of-process Azure Functions
Unlike in-process functions, out-of-process functions handle dependency injection in the Main
method of the Program
class.
Modify the HostBuilder
build pipeline to call ConfigureServices
and configure the ConnectionMultiplexer
, as shown in the following example:
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(s=>s.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect("localhost"))) // add this line
.Build();
host.Run();
}
For both in-process and out-of-process functions, you can pass the Multiplexer by injecting it into the constructor of the class housing your functions:
public class RedisTrigger
{
private readonly IConnectionMultiplexer _redis;
public RedisTrigger(IConnectionMultiplexer redis){
_redis = redis;
}
[FunctionName("RedisTrigger")]
public async Task<IActionResult> Foo(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
var db = _redis.GetDatabase();
var bar = await db.StringGetAsync("foo");
return new OkObjectResult(bar.ToString());
}
}
TLS
StackExchange.Redis natively support TLS, as shown here:
using StackExchange.Redis;
using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
namespace ConnectToRedisWithTls
{
class Program
{
const string PATH_TO_CERT_FILE = "c:\\PATH\\TO\\CERT.pfx";
static async Task Main(string[] args)
{
var configurationOptions = new ConfigurationOptions
{
EndPoints = { "redis-12000.cluster.redis.com:12000" },
Ssl = true
};
configurationOptions.CertificateSelection += delegate {
var cert = new X509Certificate2(PATH_TO_CERT_FILE, "");
return cert;
};
var redis = await ConnectionMultiplexer.ConnectAsync(configurationOptions);
Console.WriteLine(redis.GetDatabase().Ping());
}
}
}
- Modify the
PATH_TO_CERT_FILE
to match the path to your certificate - Modify the
EndPoints
setting to point to your endpoint(s) - If necessary, add a
Password
to theConfigurationOptions
To learn how to run Redis Enterprise with TLS enabled, see TLS Support.
Convert certificate format
To easily convert a .key certificate to .pfx format, use OpenSSL:
openssl pkcs12 -export -in user.crt -inkey user_private.key -certfile garantia_ca.pem -out certificate.pfx
Use SSL and a StackExchange.Redis-based provider
Sometimes you need to use a 3rd-party library, such as when running a session on a cache provider that connects to Redis with the StackExchange.Redis client. When you need to provide an SSL certificate for the connection and the 3rd-party library does not expose a public interface for it, you can “sideload” the certificate to StackExchange.Redis by setting the following environment variables:
- Set
SERedis_ClientCertPfxPath
to the path of your .pfx file - Set
SERedis_ClientCertPassword
to the password of your .pfx file