How to Distribute User Session in ASP.NET Core

Because load balancing with sticky sessions is flawed, we require distributed session state. We DON’T roll it ourselves, spoiler alert. It is advantageous to store state across page views with ASP.NET session storage. Because ASP.NET supports in-memory sessions out of the box, setting it up in single server scenarios is straightforward. As soon as there are more than one server, in-memory sessions become unusable. Since most production environments have multiple servers, the session problem must be resolved.

In a web farm, there are two options for sessions. First, each user can be locked to a particular box using a load balancer (also known as “sticky sessions” or “session affinity”). This enables us to keep using in-memory sessions. The second is changing from distributed session storage to in-memory session storage.

Because we already have Redis infrastructure in place and don’t want to complicate things further by adding a load balancer, we will use a distributed session using Redis.

Install the StackExchange Redis Distributed Cache Package

We currently employ StackExchange.for speaking with Redis. Microsoft conveniently offers a pre-made distributed cache package that makes use of StackExchange.Redis. Installing it is the first step:

PM> Install-Package Microsoft.Extensions.Caching.StackExchangeRedis

Configure Redis Based Distributed Session in ASP.NET Core

The StackExchangeRedis cache needs to be set up for use by the application. Make sure to specify which Redis instance the cache should connect to:

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

namespace MyApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // Configure Redis Based Distributed Session
            var redisConfigurationOptions = ConfigurationOptions.Parse("localhost:6379");

            services.AddStackExchangeRedisCache(redisCacheConfig =>
            {
                redisCacheConfig.ConfigurationOptions = redisConfigurationOptions;
            });

            services.AddSession(options => {
                options.Cookie.Name = "myapp_session";
                options.IdleTimeout = TimeSpan.FromMinutes(60 * 24);
            });

            // ...snip... Other ASP.NET Core configuration here!
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // Enable session for the application
            app.UseSession();

            // ...snip... Other ASP.NET Core configuration here!
        }
    }
}

Read and Write to the User’s Session

Reading and writing to the user’s session should work with the Redis cache configured:

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Controllers
{
    public class TestController : Controller
    {
        [HttpGet]
        [Route("/write-to-session")]
        public IActionResult TestWriteSession()
        {
            var value = $"Session written at {DateTime.UtcNow.ToString()}";
            HttpContext.Session.SetString("Test", value);

            return Content($"Wrote: {value}");
        }

        [HttpGet]
        [Route("/read-from-session")]
        public IActionResult TestReadSession()
        {
            var value = HttpContext.Session.GetString("Test");

            return Content($"Read: {value}");
        }
    }
}

Both user authentication and distributed sessions are now operational. The sign-up flow for users to initially create their accounts will be created next.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *