Redis has steadily established itself as a great choice of infrastructure in modern solutions. Redis is a data structures server, which provides an interface of commands used to interact with mutable data. Developers use Redis as a key/value store for quick lookups with known keys, commonly in caching. A developer operating with .NET will most likely be using the StackExchange.Redis package to access their server instance. While connection strings for Redis can vary, many online hosting platforms provide a redis-cli connection string.

This post will see how we can write an extension method that parses a redis-cli connection string we can use with the StackExchange.Redis library.

What Is Redis-CLI

redis-cli is a command-line interface (CLI) program that allows us to send commands to a Redis instance. The program can operate in two modes: Read Eval Print Loop (REPL) and single-command. The REPL mode assumes a developer is actively typing commands, reading the response, and repeating as needed. Developers can use the single-command method to issue one-off commands, and the program will print results to the standard output.

We can use the -u argument when invoking redis-cli to connect to a remote server.

redis-cli -u redis://username:password@host:port

From the CLI, we can issue commands like PING and receive a response.

redis-cli -u redis://username:password@host:port ping
PONG

So, how do we take our redis:// URI and use that in our .NET 5+ applications?

Parsing the Redis-CLI URI

Before continuing, this post assumes you are using the StackExchange.Redis NuGet package. To install the dependency, use the following command on the target .NET project.

dotnet add package StackExchange.Redis

As we saw in the previous section, the redis-cli URI has a particular pattern.

redis://username:password@host:port

Let’s convert that into a Regex pattern. We’ll also use named groups to pull the necessary values out later in the post.

^redis://(?<username>.+):(?<password>.+)@(?<host>.+):(?<port>\d+)$

Now, let’s look at how we might configure our Redis infrastructure in an ASP.NET Core application. **Note, I’ve configured the Redis dependencies in Program.cs, but the code would be identical if placed in Startup.cs.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Redis;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices(collection =>
            {
                collection.AddSingleton(services =>
                {
                    var config = services.GetRequiredService<IConfiguration>();
                    var connectionString = config["Redis"];
                    return ConnectionMultiplexer.Connect(
                        new ConfigurationOptions()
			    // our extension method
                            .FromCli(connectionString));
                });

                collection.AddScoped(services =>
                {
                    var connection = 
                        services.GetRequiredService<ConnectionMultiplexer>();
                    return connection.GetDatabase();
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

We have a FromCli extension method, which parses the format described above. How do we implement the approach? Regular Expressions of course!

using System;
using System.Text.RegularExpressions;
using StackExchange.Redis;

public static class Redis
{
    private static readonly Regex CliPattern =
        new("^redis://(?<username>.+):(?<password>.+)@(?<host>.+):(?<port>\\d+)$");

    public static ConfigurationOptions FromCli(string connectionString)
    {
        var options = new ConfigurationOptions();
        FromCli(options, connectionString);
        return options;
    }

    public static ConfigurationOptions FromCli(
        this ConfigurationOptions options, 
        string connectionString
    )
    {
        var match = CliPattern.Match(connectionString);
        if (!match.Success)
        {
            throw new ArgumentException(
                "Cli connection string was not correct. " +
                $"Be sure it follows {CliPattern} pattern.",
                nameof(connectionString));
        }

        var values = match.Groups;
        options.EndPoints.Add($"{values["host"].Value}:{values["port"].Value}");
        options.Password = values["password"].Value;
        options.User = values["username"].Value;

        return options;
    }
}

There you have it! Now you can use your redis-cli connection string with StackExchange.Redis. Hopefully, you find this extension method helpful when switching between the two different ways of accessing Redis.