ASP.NET app using Redis backed Session, using Steeltoe.io
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
Steeltoe.Extensions.Configuration.CloudFoundryCore
Steeltoe.CloudFoundry.ConnectorCore
Microsoft.Web.RedisSessionStateProvider
Microsoft.Extensions.DependencyInjection
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.
Leave a comment