Implement Sessions in Asp .Net 5(vNext) and MVC 6

Imagine you have created an MVC project and you are all set to create a session object because you want to save your current user email.

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 ASP.NET 5 session state middle ware.

Ok, so How to get it?
To install Microsoft.AspNet.Session, run the following command in the Package Manager Console

sess

Great, so now we can use Session in vNext right?
Well not yet.

We need to update Startup.cs file as below:

public void ConfigureServices(IServiceCollection services)
{ 
    // Adds a default in-memory implementation of IDistributedCache
    services.AddCaching();

    services.AddSession();  
    //// This Method may contain other code as well
}

and in Configure method write below code:

public void Configure(IApplicationBuilder app)
{
    app.UseSession();  
    //// This Method may contain other code as well
}

How to get and set session?
Ok, let us take some examples.

1. Suppose you want to use Session in your controller class:

For that you simply have to write Context.Session to access Session.

Set Session syntax:

public IActionResult Index()
{ 
    ////Context.Session.SetString("First", "I am first!"); ////Before Beta 8
    HttpContext.Session.SetString("First", "I am first!"); ////From Beta 8 onwards
    return View(); 
}

Get Session syntax:

public IActionResult Index()
{ 
    ////var myValue = Context.Session.GetString("First"); ////Before Beta 8
    var myValue = HttpContext.Session.GetString("First"); ////From Beta 8 onwards
    return View(); 
}

2. Suppose you want to use Session in a normal class:

If you’re 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);
 }

So, whole SessionUtility would be as below:

public class SessionUtility 
{
   private readonly IHttpContextAccessor HttpContextAccessor;

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

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

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

and it would be registered as below:

services.AddTransient<SessionUtility>();

Here SessionUtility should be registered only as Transient or Scoped and not Singleton as HttpContext is per-request based.

Please note that i have used it with key value pair of string but you can create same Session utility for complex scenario.

Now, Suppose you want to check how many times a Visitor have visited your site.

For that you need to add below code in your startup.cs:

public void Configure(IApplicationBuilder app)
{
    app.UseSession();

    app.Map("/session", subApp =>
    {
        subApp.Run(async context =>
        {
             int visits = 0;
             visits = context.Session.GetInt32("visits") ?? 0;
             context.Session.SetInt32("visits", ++visits);
             await context.Response.WriteAsync("Counting: You have visited our page this many times: " + visits);
        });
     });
}

Remember!
If you have follow above steps and you still can not get the success then you might need a look in your project.json file if it contains below piece of code:

"frameworks": {
 "dnx451": { },
 "dnxcore50": { } // <-- Remove this if it is in your project.json file.
},

Reason?
Because Asp.Net 5 Sessions aren’t supported by the DNX Core Runtime.

Nuget package site: https://www.nuget.org/packages/Microsoft.AspNet.Session/

Session is still in it’s beta versions so there might some changes would come that will be updated in this post.

Stay tuned for more updates!

19 thoughts on “Implement Sessions in Asp .Net 5(vNext) and MVC 6

  1. As soon as I add app.UseSession(); I get this error on running:

    System.InvalidOperationException: Unable to resolve service for type ‘Microsoft.Framework.Caching.Distributed.IDistributedCache’ while attempting to activate ‘Microsoft.AspNet.Session.DistributedSessionStore’.
    at Microsoft.Framework.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
    at Microsoft.Framework.DependencyInjection.ServiceLookup.Service.CreateCallSite(ServiceProvider provider, ISet`1 callSiteChain)
    at Microsoft.Framework.DependencyInjection.ServiceProvider.GetResolveCallSite(IService service, ISet`1 callSiteChain)
    at Microsoft.Framework.DependencyInjection.ServiceProvider.GetServiceCallSite(Type serviceType, ISet`1 callSiteChain)
    at Microsoft.Framework.DependencyInjection.ServiceProvider.b__7_0(Type key)
    at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
    at Microsoft.Framework.DependencyInjection.ServiceProvider.GetService(Type serviceType)
    at Microsoft.Framework.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
    at Microsoft.Framework.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
    at Microsoft.AspNet.Builder.UseMiddlewareExtensions.c__DisplayClass2_0.b__0(RequestDelegate next)
    at Microsoft.AspNet.Builder.Internal.ApplicationBuilder.Build()
    at Microsoft.AspNet.Hosting.Internal.HostingEngine.BuildApplication()
    at Microsoft.AspNet.Hosting.Internal.HostingEngine.Start()
    at Microsoft.AspNet.Loader.IIS.RuntimeHttpApplication.ApplicationStart(IHttpApplication application)
    at Microsoft.AspNet.Loader.IIS.HttpApplicationBase.InvokeApplicationStart(IHttpApplication application)

    Like

  2. I have a error when instance class Error CS7036 There is no argument given that corresponds to the required formal parameter ‘httpContextAccessor’ of ‘SessionUtility.SessionUtility(IHttpContextAccessor)’ EjemplosMVC.DNX 4.5.1

    Like

      1. Hi, I registred services.AddTransient() in Startup.cs ConfigureServices section. but when i instance from controller
        var Sess = new SessionUtility(); show error :There is no argument given that corresponds to the required formal parameter ‘httpContextAccessor’ of ‘SessionUtility.SessionUtility(IHttpContextAccessor)’

        public class SessionUtility
        {
        private readonly IHttpContextAccessor HttpContextAccessor;

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

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

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

        Like

  3. So… Sessions require Caching? Is it possible to use in-memory caching for general use at the same time as SQL server backed sessions?

    Like

    1. Hi Simon,

      I asked .Net team regarding this and they answered as below:

      Yes, they shouldn’t interfere with each other. In memory caching is registered as an IMemoryCache, where SQL is registered as an IDistributedCache. Session uses IDistributedCache.

      Neel

      Like

      1. Thanks, Neel!

        I wonder if you know of any samples that show how to properly configure the services object with “In Memory Cache” and simultaneous “Sql Server Sessions”.? I can’t seem to work it out at all.

        Like

      2. Hi Simon, I just saw that you have already got answer in Github. Anyways for those who have same doubt can make it work as below:

        AddCaching(); // Add IMemoryCache and IDistributedCache

        AddSqlServerCache(); // overwrite IDistributedCache registration from AddCaching with SQL backing

        AddSession(); // which will now resolve to using SQL backed IDistributedCache

        Like

      3. That actually ended up being incorrect. You have to “AddSqlServerCache” *first*. So, it’s

        AddSqlServerCache();
        AddCaching();
        AddSession();

        It looks like the behavior is that AddCaching does not overwrite the IDistributedCache added by AddSqlServerCache, but rather makes use of it. If no IDistributedCache has been added by the time you call AddCaching, it adds its own implementation.

        I find this behavior confusing since it’s not intuitive (a later call, in my mind, should override an earlier call). ADditionally, since there is no way to know which services each call adds to the pipeline by looking at the method name or the intellisense comments, it becomes a game of searching the source code.

        Hopefully the final documentation will at least include this information.

        Like

  4. Hi,

    I have seen this kind of examples using “SessionUtility”, but anyone shows how to use this class. I’m trying to use it, but I need to pass some constructor value.

    How can I use this class?

    Like

Leave a comment