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.
 
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 SessionId cookie and they are deleted when the Browser session ends.

At the Server end, 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 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.Session package provides middleware to manage the sessions in ASP.NET Core. To use session in our Application, we need to add this package as a dependency in project.json file.
 
Project.json
  1. {  
  2.   "version""1.0.0-*",  
  3.   "buildOptions": {  
  4.     "debugType""portable",  
  5.     "emitEntryPoint"true  
  6.   },  
  7.   "dependencies": {},  
  8.   "frameworks": {  
  9.     "netcoreapp1.0": {  
  10.       "dependencies": {  
  11.         "Microsoft.NETCore.App": {  
  12.           "type""platform",  
  13.           "version""1.0.1"  
  14.         },  
  15.         "Microsoft.AspNetCore.Mvc""1.0.1",  
  16.         "Microsoft.AspNetCore.Server.Kestrel""1.0.1",  
  17.         "Microsoft.AspNetCore.Routing""1.0.1",  
  18.         "Microsoft.AspNetCore.Session" : "1.0.1"  
  19.       },  
  20.       "imports""dnxcore50"  
  21.     }  
  22.   }  
  23. }  
The next step is to configure session in Startup class. We need to call "AddSession" method in ConfigureServices method of startup class. The "AddSession" method has one overload method, which accepts various session options such as Idle Timeout, Cookie Name and Cookie Domain etc. If we do not pass the session options, the system will take the default options. Now, we need to call "UseSession" method in Configure method of startup class. This method enables the session for the Application.
 
Startup.cs
  1. using System;  
  2. using Microsoft.AspNetCore.Builder;  
  3. using Microsoft.AspNetCore.Hosting;  
  4. using Microsoft.AspNetCore.Http;  
  5. using Microsoft.Extensions.DependencyInjection;  
  6.   
  7. namespace WebApplication {  
  8.     public class Startup {  
  9.         public void Configure(IApplicationBuilder app)  
  10.         {  
  11.             app.UseSession();  
  12.             app.UseMvc();  
  13.             app.Run(context => {  
  14.                 return context.Response.WriteAsync("Hello Readers!");  
  15.             });  
  16.         }  
  17.   
  18.         public void ConfigureServices(IServiceCollection services)  
  19.         {  
  20.             services.AddMvc();  
  21.             services.AddSession(options => {   
  22.                 options.IdleTimeout = TimeSpan.FromMinutes(30);   
  23.             });  
  24.         }       
  25.     }  
  26. }  
It is important to call "UseSession" method before the "UseMvc" method in Configure method of startup class. If we call “UseMvc” method before “UseSession” method, the system will throw an exception.
 
 
 
How to access the session

We can use session from HttpContext, once it is installed and configured. To use session in controller class, we need to reference "Microsoft.AspNet.Http" in controller. There are three methods that enables us to set the session value, which are Set, SetInt32 and SetString. The "Set" method accepts byte array as an argument. The SetInt32 and SetString method 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 byte of arrays.
 
The main reason behind storing bytes array is to make sure that session values are serializable for the storage on remote Servers. Apart from int and string, we need to serialize to byte array to store it in session.
 
Example

In the example given below, I have set my name into session in first request and retrieved the session value in another request.
  1. using Microsoft.AspNetCore.Http;  
  2. using Microsoft.AspNetCore.Mvc;  
  3.   
  4. public class HomeController : Controller  
  5. {  
  6.   
  7.     [Route("home/index")]  
  8.     public IActionResult Index()  
  9.     {  
  10.         HttpContext.Session.se.SetString("name","Jignesh Trivedi");  
  11.         return View();  
  12.     }  
  13.     [Route("home/GetSessionData")]  
  14.     public IActionResult GetSessionData()  
  15.     {  
  16.         ViewBag.data = HttpContext.Session.GetString("name");;  
  17.         return View();  
  18.     }  
  19. }  
Output

 
 
Custom Session Extension methods

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

In the example given below, I have created an extension method to set double value to session and get double value from session.
  1. using System;  
  2. using Microsoft.AspNetCore.Http;  
  3. public static class SessionExtensions  
  4. {  
  5.     public static double? GetDouble(this ISession session, string key)  
  6.     {  
  7.         var data = session.Get(key);  
  8.         if (data == null)  
  9.         {  
  10.             return null;  
  11.         }  
  12.         return BitConverter.ToDouble(data, 0);  
  13.     }   
  14.   
  15.     public static void SetDouble(this ISession session, string key, double value)  
  16.     {  
  17.         session.Set(key, BitConverter.GetBytes(value));  
  18.     }  
  19. }  
Usage of the extension method
  1. using Microsoft.AspNetCore.Http;  
  2. using Microsoft.AspNetCore.Mvc;  
  3. public class HomeController : Controller  
  4. {  
  5.   
  6.     [Route("home/index")]  
  7.     public IActionResult Index()  
  8.     {  
  9.         HttpContext.Session.SetString("name","Jignesh Trivedi");  
  10.         HttpContext.Session.SetDouble("Percentage",75.56);  
  11.         return View();  
  12.     }  
  13.     [Route("home/GetSessionData")]  
  14.     public IActionResult GetSessionData()  
  15.     {  
  16.         ViewBag.data = HttpContext.Session.GetString("name");  
  17.         ViewBag.Percent = HttpContext.Session.GetDouble("Percentage");  
  18.         return View();  
  19.     }  
  20. }  
Output

 
 
Store Complex Data in to Session

As we are aware, session is able to store only 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 session. Here, I am converting the complex object into JSON and store it as a string. Later, I am retrieving it as a string and de-serialize to original object.

Thus, I have written the extension method for set and get complex object to session.
  1. using System;  
  2. using Microsoft.AspNetCore.Http;  
  3. using Newtonsoft.Json;  
  4.   
  5. public static class SessionExtensions  
  6. {  
  7.     public static T GetComplexData<T>(this ISession session, string key)  
  8.     {  
  9.         var data = session.GetString(key);  
  10.         if (data == null)  
  11.         {  
  12.             return default(T);  
  13.         }  
  14.         return JsonConvert.DeserializeObject<T>(data);  
  15.     }   
  16.   
  17.     public static void SetComplexData(this ISession session, string key, object value)  
  18.     {  
  19.         session.SetString(key, JsonConvert.SerializeObject(value));  
  20.     }  
  21. }  
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 session.
  1. public class User   
  2. {  
  3.     public string Name { getset; }  
  4.     public double Percentage { getset; }  
  5. }  
Action method
  1. [Route("home/SetComplexData")]  
  2. public IActionResult SetComplexData()  
  3. {  
  4.     User user = new User();  
  5.     user.Name = "Jignesh Trivedi";  
  6.     user.Percentage = 75.45;             
  7.       
  8.     HttpContext.Session.SetComplexData("UserData", user);  
  9.     return View("index");  
  10. }  
  11. [Route("home/GetComplexData")]  
  12. public IActionResult GetComplexData()  
  13. {  
  14.     ViewBag.data = HttpContext.Session.GetComplexData<User>("UserData");  
  15.     return View();  
  16. }  
Summary

The main advantages 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 session is slightly different than the classic ASP.NET Application. This article helps us to understand how to install, configure and use session with ASP.NET Core.