ASP.NET app using Redis backed Session, using Steeltoe.io

Alfus Jaganathan
Cloud Solutions Architect
February 15, 2019
Rate this article
Views    6165

Introduction

In most of the web applications, we use session as a user-session based caching mechanism, where we store data for reusability. In a higher level there are 2 types of session store, In-Proc and Out-Proc. In-Proc stores the data within the application process (App Domain) where as Out-Proc stores the data in an external store such as SQL Server or Asp.NET state server. For more information on session, please refer to https://docs.microsoft.com/en-us/previous-versions/ms178581(v=vs.140)

Now, coming to cloud and 12-factors-processes, it states that a cloud native application should be stateless and share nothing. As we know that session is stateful, we need to move it away from the application process, if we are building an application, targeting cloud platforms like PCF(PAS) or any similar PaaS platforms.

Though we have several Out-Proc options available, I picked Redis, as it is one of the most reliable and fast distributed storage available, especially in most of the the PaaS platforms. But then we have various complications on providing connections and related configurations to the application session providers. Here we solve them very easily using Steeltoe and Microsoft’s Redis session state provider.

Let’s go through the steps one-by-one below.

1. Pre-requisites

  • Make sure you have Visual Studio (latest version) installed in your machine
  • Make sure you have Redis latest version installed in your machine, if not you can install from here

2. Install Nuget Packages

Install latest version of below packages from NuGet.org

  1. Steeltoe.Extensions.Configuration.CloudFoundryCore
  2. Steeltoe.CloudFoundry.ConnectorCore
  3. Microsoft.Web.RedisSessionStateProvider
  4. Microsoft.Extensions.DependencyInjection
  5. Microsoft.Extensions.Configuration

3. Web.Config File Changes

As soon as you install the package “Microsoft.Web.RedisSessionStateProvider“, you will see a session section added, so that you can explicitly provide the connection string parameters. But it is not that very easy or a good practice to hardcode or manually modifying the configuration values. So we are going to use a different approach of serving the connection string via runtime object.

So we have to modify the session section as below.

<sessionState mode="Custom" customProvider="RedisSessionStateStore">
      <providers>
        <add name="RedisSessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" 
             settingsClassName="{setting class name}" 
             settingsMethodName="{setting method name}" />
      </providers>
    </sessionState>

Also add machineKey, section as below. Remember to generate a new machine key for each application. You can use https://www.developerfusion.com/tools/generatemachinekey to generate a new machine key and replace below.

<machineKey validationKey="{placeholder: Generated validation key}"
                decryptionKey="{placeholder: Generated validation key}"
                validation="SHA1" decryption="AES"/>

4. App Configuration Setup

Now, we have to create a class which can server the application configuration (IConfigurationRoot) and IConnectionMultiplexer. A sample code snippet is given below for your quick reference.

public class ServerConfig
    {
        static IHost host;
        public static void Register(string environment)
        {
            host = new HostBuilder()
                .ConfigureAppConfiguration((builderContext, configBuilder) =>
                {
                    configBuilder.AddJsonFile("appSettings.json", false, false);
                    configBuilder.AddJsonFile($"appsettings.{environment}.json", optional: true);
                    configBuilder.AddEnvironmentVariables();
                })
                .ConfigureServices((builderContext, services) =>
                {
                    services.AddRedisConnectionMultiplexer(builderContext.Configuration);
                })
                .Build();
        }
        public static T GetService<T>()
        {
            return host.Services.GetService<T>();
        }
    }

5. Redis Configuration Setup

As discussed above, we need to server the connection string at runtime. From the above code, services.AddRedisConnectionMultiplexer will add an instance of IConnectionMultliplexer which also dynamically pulls the Redis connection string (Steeltoe magic), whether you run the application in local machine or in PCF (provided the application is bounded to a Redis service instance). To server this purpose we create a class as below and apply the changes to the session section of web.config as described later.

namespace Steeltoe.Redis.Session.Sample
{
    public class RedisConfig
    {
        static IConnectionMultiplexer connectionMultiplexer;
        static RedisConfig()
        {
            connectionMultiplexer = ServerConfig.GetService<IConnectionMultiplexer>() 
                ?? throw new ArgumentNullException(nameof(IConnectionMultiplexer));
        }
        
        public static string GetConnectionString()
        {
            return connectionMultiplexer.Configuration;
        }
    }
}

Since we got the class name and method name which serves the connection string here, we need to update the session section with class name as Steeltoe.Redis.Session.Sample.RedisConfig and methodName as GetConnectinString.

<sessionState mode="Custom" customProvider="RedisSessionStateStore">
      <providers>
        <add name="RedisSessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" 
             settingsClassName="Steeltoe.Redis.Session.Sample" 
             settingsMethodName="GetConnectionString" />
      </providers>
    </sessionState>

6. Wiring The Changes

We are at the final stage of connecting the changes to the application. Fo this, we need to add the below code in Application_Start under Global.asax.cs, which will configure the services and configuration added in ServerConfig during application startup.

ServerConfig.Register("development");

7. Testing The Application

Now we are all set to run and test the application. You can add any simple code to test the session operations based on your convenience. Once you run the application you can use Redis-cli command KEYS * to verify if the keys are available in Redis.

If you are running the application in your local machine, Steeltoe will connect to the local Redis regardless of providing an explicit configuration. Similarly, if you push the application to PCF and bind the application to a Redis instance, you should see Steeltoe connect to the Redis instance seamlessly.

Code Reference

Find the working sample application here https://github.com/alfusinigoj/aspnet_redis_session_using_steeltoe for easy reference and coding.

Hope you had fun coding!

Subscribe To Our Newsletter
Loading

Leave a comment