Implement Session in .Net Core(2.0)

Session in .Net Core1 (1)

Note – You can find the source code of my sample application here.

You can find all of my  .Net core posts here.

In this post, we will see how to implement session in your .Net Core applications.

What is Session state?

Session state is a feature in ASP.NET Core that you can use to save and store user data while the user browses your web app. Consisting of a dictionary or hash table on the server, session state persists data across requests from a browser. The session data is backed by a cache.

Where is the session object in .Net Core?

Imagine you have created a .Net Core project and you are all set to create a session object because you want to save your current user details or anything.

But after few minutes you will realize that Session object is not working as it was before.

Oh! Why is it so?
It is because .Net team has created a NuGet package for Session which is nothing but a very fresh .Net Core session state middleware. After installing the package, you can find the session object under HttpContext.

Let us start step by step.

prerequisite:

  • Visual studio 2017 community edition, download here
  • .Net Core 2.0 SDK from here (I have written a post to install SDK here)

Create the Web application using .Net Core 2.0 template in VS 2017

Once you have all these installed, open your Visual Studio 2017 -> Create New Project -> Select Core Web application:

session1

Click on Ok and in next window, select Web Application as shown below:

session2

Visual Studio will create a well-structured application for you.

Install Session package from Nuget

Next step is to add Session package from Nuget for .Net Core.

Open Nuget manager and search for Microsoft.AspNetCore.Session and then click on Install:

session3

We are now required to add a couple of lines into the Startup.cs class

Open Startup.cs class -> Configure method and add app.UseSession() as shown below:


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();

app.UseSession();

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

And in ConfigureService method add services.AddSession() with some configurations as shown below:


public void ConfigureServices(IServiceCollection services)
{

services.AddDistributedMemoryCache();

services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(1);//You can set Time
});

services.AddMvc();
}

We have set session expiry time to 1 minute, set as per your need.

That is it. Now you can use sessions in your .Net Core applications.

Use Session in your controller class

For that, you simply have to write HttpContext.Session to get\set Session. This data is stored in IDistributedCache  cache.

You can use SQL server cache or Redis cache instead of Distributed memory cache.

Set Session syntax:


public IActionResult Index()
{
HttpContext.Session.SetString("name", "Neel Bhatt");
HttpContext.Session.SetString("email", "neel.bhatt40@gmail.com");
return View();
}

Get Session syntax:


public IActionResult Contact()
{
ViewBag.Name = HttpContext.Session.GetString("name");
ViewBag.Email = HttpContext.Session.GetString("email");
ViewData["Message"] = "Your contact page.";

return View();
}

Add ViewBag in the Contact.cshtml and run the application. You can now see the name and email which we set in the session:

session4

Note that we have set session expiry time to 1 minute, so after 1 minute if you will load the page then the session would be expired and hence data will vanish:

session5

Now if you click on Home and then Contact then data will appear again because we are setting session in Index action. Set session time as per your need.

Use session in the Service\Class

If you are not in a controller, you can still access the HttpContext by injecting IHttpContextAccessor as shown below:


private readonly IHttpContextAccessor _httpContextAccessor;

public SessionUtility(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}

//Set Session syntax

public void SetSession(string key, string value)
{
HttpContextAccessor.HttpContext.Session.SetString(key, value);
}

//Get Session syntax

public string GetSession(string key)
{
return HttpContextAccessor.HttpContext.Session.GetString(key);
}

In your Startup.cs, you need to register IHttpContextAccessor as a service like shown below :


public void ConfigureServices(IServiceCollection services)

{

services.AddMvc();

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

}

Note – From ASP.NET Core 2.1 onwards the AddHttpContextAccessor helper extension method was added to correctly register the IHttpContextAccessor with the correct lifetime (singleton). So, in ASP.NET Core 2.1 and above, the code should be:

services.AddHttpContextAccessor();

Session extension for complex objects

As we have seen above, we can get and set simple objects like string, integer easily with the session. But what if we want to use some complex objects in session.

In such case, we can create an extension which can then be used to use sessions for complex objects.

For example, you have TestClass and you want to store the instance of this object into the session. For that let us create the extension first:


public static class SessionExtensions
{
public static void SetObjectAsJson<T>(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}

public static T GetObjectFromJson<T>(this ISession session, string key)
{
var value = session.GetString(key);

return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
}
}

Now you can store your complex objects as shown below:


var myComplexTestObject = new MyTestClass();
HttpContext.Session.SetObjectAsJson("Test", myComplexTestObject);

and get them as below:


var myComplexTestObject= HttpContext.Session.GetObjectFromJson<Test>("Test");

As shown below, an instance of the object gets easily from the session:

session6

 

Note – You can find the source code of my sample application here.

Hope it helps.

 

 

 

 

 

 

14 thoughts on “Implement Session in .Net Core(2.0)

  1. Thank you, very helpful !!! I have a quick question, regarding the last bit on “Session extension for complex objects”, where would you put the class extension code? should it be put in the Controller of the object am trying to save in the session, or just an independent library class as helper?

    Like

    1. Btw the code which you are referring is when you want to use the session in Views. My post mainly concentrates on the controllers and services for cs classes.

      Like

  2. I have been trying to figure this session thing out for a while. I think I have Startup.cs configured correctly:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using OM2018.Data;
    using Microsoft.EntityFrameworkCore;

    namespace OM2018
    {
    public class Startup
    {
    public Startup(IConfiguration configuration)
    {
    Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
    services.Configure(options =>
    {
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDistributedMemoryCache(); // Adds a default in-memory implementation of IDistributedCache
    services.AddSession();

    services.AddDbContext(options =>
    options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”)));

    // Add MVC services to the services container.
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    else
    {
    app.UseExceptionHandler(“/Home/Error”);
    }

    app.UseStaticFiles();
    app.UseCookiePolicy();

    // IMPORTANT: This session call MUST go before UseMvc()
    app.UseSession();

    app.UseMvc(routes =>
    {
    routes.MapRoute(
    name: “default”,
    template: “{controller=Home}/{action=Index}/{id?}”);
    });
    }
    }
    }

    In my Controller, I can set a session and immediately get its value, but if I redirect, the value is no longer there:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult AdminLogin([Bind(“UserName”, “Password”)] Administrator administrator)
    {
    Console.WriteLine(“AdminLogin: ” + administrator.UserName + “, ” + administrator.Password);
    var admin = _context.Administrators.Where(x => x.UserName == administrator.UserName
    && x.Password == administrator.Password).FirstOrDefault();

    if (admin != null)
    {
    HttpContext.Session.SetString(“IsAdmin”, JsonConvert.SerializeObject(true));
    }

    var IsAdmin = HttpContext.Session.GetString(“IsAdmin”);

    return RedirectToAction(“Index”);
    }

    ///
    /// Shows the administrator interface
    ///
    public IActionResult Index()
    {
    //HttpContext.Session.SetString(“Test”, “Chris Rules!”);
    //ViewData[“Message”] = HttpContext.Session.GetString(“Test”);
    var IsAdmin = HttpContext.Session.GetString(“IsAdmin”);

    if (HttpContext.Session.GetString(“IsAdmin”) != null
    && HttpContext.Session.GetString(“IsAdmin”) == “true”)
    {
    ViewData[“Title”] = “Administrator Page”;
    ViewData[“Message”] = “Administrator Page”;
    return View();
    }
    else
    {
    return RedirectToAction(“AdminLogin”);
    }
    }

    I’m not sure why this is not working, but it is really important that I be able to persist data for more than one page view. Any help would be appreciated!!! 🙂

    Like

Leave a comment