Session State In ASP.NET Core

Introduction

Web applications work on HTTP protocol and HTTP is a stateless protocol. Every HTTP request is treated as an independent request. The Server does not have knowledge about the variable values, which are being used in the previous request.

The session is a feature in ASP.NET Core that enables us to save/store the user data. Session stores the data in the dictionary on the Server and SessionId is used as a key. The SessionId is stored on the client at cookie. The SessionId cookie is sent with every request. The SessionId cookie is per browser and it cannot be shared between the browsers. There is no timeout specified for the SessionId cookie and they are deleted when the Browser session ends.

At the Server end, the session is retained for a limited time. The default session timeout at the Server is 20 minutes but it is configurable.

Sessions are of two types, namely In-Proc or In-memory and Out-Proc or Distributed session. If our session is in-memory and our application is hosted on a Web-Farm environment, we need to use sticky sessions to tie each session to a specific Server whereas an Out-Proc session does not require sticky sessions and they are the most preferred way to use sessions in our application.

Configuring session

Microsoft.AspNetCore.The session package provides middleware to manage the sessions in ASP.NET Core. To use the session in our Application, we need to add this package as a dependency in the project.json file.

Project.json

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.1"
        },
        "Microsoft.AspNetCore.Mvc": "1.0.1",
        "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
        "Microsoft.AspNetCore.Routing": "1.0.1",
        "Microsoft.AspNetCore.Session": "1.0.1"
      },
      "imports": "dnxcore50"
    }
  }
}

The next step is to configure the session in the Startup class. We need to call the "AddSession" method in the ConfigureServices method of the startup class. The "AddSession" method has one overload method, which accepts various session options such as Idle Timeout, Cookie Name Cookie Domain, etc. If we do not pass the session options, the system will take the default options. Now, we need to call the "UseSession" method in the Configure method of the startup class. This method enables the session for the Application.

Startup. cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace WebApplication
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.UseSession();
            app.UseMvc();
            app.Run(context =>
            {
                return context.Response.WriteAsync("Hello Readers!");
            });
        }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(30);
            });
        }
    }
}

It is important to call the "UseSession" method before the "UseMvc" method in the Configure method of the startup class. If we call the “UseMvc” method before the “UseSession” method, the system will throw an exception.

UseSession

How to access the session?

We can use the session from HttpContext, once it is installed and configured. To use the session in the controller class, we need to reference "Microsoft.AspNet.Http" in the controller. There are three methods that enables us to set the session value, which are Set, SetInt32, and SetString. The "Set" method accepts a byte array as an argument. The SetInt32 and SetString methods are the extension methods of Set and they internally cast byte array to int and string respectively. Same as there are three methods that are used to retrieve the value from the session: Get, GetInt32, and GetString. The Get method returns a byte of arrays.

The main reason behind storing bytes array is to make sure that session values are serializable for storage on remote Servers. Apart from int and string, we need to serialize to a byte array to store it in session.

Example

In the example given below, I have set my name into the session in the first request and retrieved the session value in another request.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
    [Route("home/index")]
    public IActionResult Index()
    {
        HttpContext.Session.SetString("name", "Jignesh Trivedi");
        return View();
    }
    [Route("home/GetSessionData")]
    public IActionResult GetSessionData()
    {
        ViewBag.data = HttpContext.Session.GetString("name");
        return View();
    }
}

Output

Output

Custom Session Extension methods

As discussed earlier, there are two extension methods to get the data from the session and set the data to the session available, namely GetInt32 and GetString, SetInt32 and SetString. Similarly, we can add our custom extension methods to get and set the value in the session.

In the example given below, I have created an extension method to set a double value to the session and get a double value from the session.

using System;
using Microsoft.AspNetCore.Http;
public static class SessionExtensions
{
    public static double? GetDouble(this ISession session, string key)
    {
        var data = session.Get(key);
        if (data == null)
        {
            return null;
        }
        return BitConverter.ToDouble(data, 0);
    }
    public static void SetDouble(this ISession session, string key, double value)
    {
        session.Set(key, BitConverter.GetBytes(value));
    }
}

Usage of the extension method.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
    [Route("home/index")]
    public IActionResult Index()
    {
        HttpContext.Session.SetString("name", "Jignesh Trivedi");
        HttpContext.Session.SetDouble("Percentage", 75.56);
        return View();
    }
    [Route("home/GetSessionData")]
    public IActionResult GetSessionData()
    {
        ViewBag.data = HttpContext.Session.GetString("name");
        ViewBag.Percent = HttpContext.Session.GetDouble("Percentage");
        return View();
    }
}

Output

Session

Store Complex Data in Session

As we are aware, the session is able to store only the byte of an array. Compared to the previous version, ASP.NET Core does not perform any operation such as serialization/ de-serialization on the values stored in the session. Here, I am converting the complex object into JSON and storing it as a string. Later, I retrieve it as a string and de-serialize it to the original object.

Thus, I have written the extension method for setting and getting complex objects to the session.

using System;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
public static class SessionExtensions
{
    public static T GetComplexData<T>(this ISession session, string key)
    {
        var data = session.GetString(key);
        if (data == null)
        {
            return default(T);
        }
        return JsonConvert.DeserializeObject<T>(data);
    }
    public static void SetComplexData(this ISession session, string key, object value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }
}

Usage of the extension method

In the following example, I have created one public class and within controller action method, created the instance of the class, stored some data, and sent it for storing in session. Similarly, I created one action method to retrieve the complex data from the session.

public class User
{
    public string Name { get; set; }
    public double Percentage { get; set; }
}

Action method

[Route("home/SetComplexData")]
public IActionResult SetComplexData()
{
    User user = new User();
    user.Name = "Jignesh Trivedi";
    user.Percentage = 75.45;    
    HttpContext.Session.SetComplexData("UserData", user);
    return View("index");
}
[Route("home/GetComplexData")]
public IActionResult GetComplexData()
{
    ViewBag.data = HttpContext.Session.GetComplexData<User>("UserData");
    return View();
}

Summary

The main advantage of ASP.NET Core is that it supports modularity. It means that we need to add the module, as we wish to use it in our application. The usage of the session is slightly different than the classic ASP.NET Application. This article helps us to understand how to install, configure, and use sessions with ASP.NET Core.