Sessions in ASP.NET Core

4.67 (48 votes)

ASP.NET Core is being designed so that your application is only dependent on features that it actually needs. This is achieved in large part by creating a composable framework, where the developer opts in to non-essential features - a number of which are baked in to traditional versions of ASP.NET. One of the features that this applies to is Session State. This article looks at how to obtain and use session state in ASP.NET Core applications.

If you are new to ASP.NET, session state is a mechanism that enables you to store and retrieve user specific values temporarily. These values can be stored for the duration of the visitor's session on your site. In most cases, they are stored in server memory, although options exist for using persistent and/or distributed storage mechanisms if, for example, you are using multiple web servers for your application (web farm etc). This article is only interested in the in-memory option. The type of data you will use session state for is anything that relates to the current user. It might be their name, or a discount level they are entitled to, or anything that you don't want to repeatedly query a database for.

Session management in ASP.NET Core is delivered via a pluggable component, or "middleware" and is available in a Nuget package called Microsoft.AspNet.Core.Session. When you use session management, you also need a persistence mechanism for session variables. In-memory storage is also available as an optional package called Microsoft.Extensions.Caching.Memory. To make them available to your application, add the following entries to the dependencies node of your project.json file:

"Microsoft.AspNetCore.Session": "1.0.0l",
"Microsoft.Extensions.Caching.Memory": "1.0.0"

You should see "Restoring..." appear next to the References node in Solution Explorer and the session package being added.

ASP.NET  Core  Session

Now that the packages are available to your application, you can opt in to using them. You do this in the ConfigureServices method of the Startup class (Startup.cs file).

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();
    services.AddCaching();
    services.AddSession(options => { 
            options.IdleTimeout = TimeSpan.FromMinutes(30); 
            options.CookieName = ".MyApplication";
        });
}

The highlighted lines show the code you need to add to the ConfigureServices method to register both caching and session with the services used in your application. The method takes an Action<SessionOptions> delegate that enables you to change the default options such as the location for session cookies, or the default timeout period (which is 20 minutes as in previous versions). The sample code above sets the timeout value to 30 minutes. This means that if a user is idle for more then 30 minutes, the session expires and its contents are removed from memory (if that is the backing store you choose to use). It also changes the name of the cookie used to manage sessions, which by default is .AspNet.Session.

At this point, you have included the required packages for session management within your solution and then registered them as services. Now you need to tell the application to use the session management features. You do this in the Configure method of the StartUp.cs file, which is where you register all middleware, but make sure you add session to the pipeline before adding MVC. :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseSession();
    //removed for brevity
}

You can start setting and getting session values after you have referenced Microsoft.AspNetCore.Http in your controller:

using Microsoft.AspNetCore.Http;

There are three methods that enable you to set session values: SetInt32, SetString and Set, which takes a byte array as an argument. This is very different to the traditional session API, which allows you to set a session value by assigning any type to a session key. The new session framework stores items as byte arrays, and internally, SetInt and SetString converts the ints and strings that you pass to a byte array. The main reason behind this decision appears to be to ensure that session values are serialisable for storage on remote servers. The only way to store other types of values is to implement the serialisation to byte arrays yourself. I look at that shortly, but in the meantime, here's how you would use the SetInt32 and SetString methods from within your controller to create and set some session variables:

public IActionResult Index()
{
    HttpContext.Session.SetString("Name", "Mike");
    HttpContext.Session.SetInt32("Age", 21);
    return View();
}

And here's how you might retrieve those values to be passed to a View:

public IActionResult About()
{
    ViewBag.Name = HttpContext.Session.GetString("Name");
    ViewBag.Age = HttpContext.Session.GetInt32("Age");
    return View();
}

There is also a Get method that returns a byte array. As I mentioned earlier, if you want to set other types as session variables, you need to take care of serialisation yourself. You could do this at the point of setting values, but a more reusable approach can be achieved by creating your own extension methods on ISession. The following example shows how you might implement GetBoolean and SetBoolean methods:

public static class SessionExtensions
{
    public static bool? GetBoolean(this ISession session, string key)
    {
        var data = session.Get(key);
        if (data == null)
        {
            return null;
        }
        return BitConverter.ToBoolean(data, 0);
    } 

    public static void SetBoolean(this ISession session, string key, bool value)
    {
        session.Set(key, BitConverter.GetBytes(value));
    }
}

Now you can use these methods too:

public IActionResult Index()
{
    Context.Session.SetString("Name", "Mike");
    Context.Session.SetInt32("Age", 21);
    Context.Session.SetBoolean("Fibber", true);
    return View();
}
public IActionResult About()
{
    ViewBag.Name = Context.Session.GetString("Name");
    ViewBag.Age = Context.Session.GetInt32("Age");
    ViewBag.Liar = Context.Session.GetBoolean("Fibber");
    return View();
}

There are two other methods of interest. One is the Remove method which allows you to delete individual values from the session collection by key:

Context.Session.Remove("Name");

The other is the Clear method. This removes all keys and values associated with the session. There is no obvious counterpart to the pre-ASP.NET Core Abandon method which ends the session.

Session Events

Classic ASP.NET includes a couple of session-related events: Session_Start and Session_End, which you can access via global.asax in order to execute code. In ASP.NET Core 1.0 , you can query the session collection using middleware to establish if a session has already been established to replicate the Session_Start event, but there are no plans to introduce an equivalent to Session_End. Since one of the driving forces behind ASP.NET Core is "cloud-readiness", the focus on session management design has been to make it work in a distributed scenario. Session_End only ever fired when sessions used inproc mode (local server memory) and the team have stated that they won't add features that only work locally.

Webucator, a specialist provider of online ASP.NET training have produced a video version of this article:

Summary

The purpose of this article is to introduce the fact that session state is an opt-in component in ASP.NET Core 1.0 and features some differences in method names and usage when compared with traditional ASP.NET. The example here used memory as a backing store for session values, although the limitations of this approach are still the same as in previous versions of ASP.NET. Memory is volatile, and cannot be relied upon. It can be cleared as a result of a number of causes outside of the developer's control. In future articles, I will look at alternative persistence stores.

You might also like...

Date Posted:
Last Updated:
Posted by:
Total Views to date: 72491

19 Comments

- Chris R

Nice writeup.

UseInMemorySession wraps UseSession, you don't need both.

- Mike

@Chris,

Thanks for your comment. I've updated the article to reflect that.

- George Kinsman

You could probably create a generic wrapper of Get<T> and Set<T> using JSON as the serialisation method which would be pretty flexible.

- Mike

@George

There's discussion about a Get<T> and Set<T> option here: https://github.com/aspnet/Session/issues/3

- Joel

Great article! But I still have one problem. I'm trying to use Context.Session.SetInt() and Context.Session.GetInt() in _ViewStart.cshtml - when I type the code, those methods are recognized fine. But when I view the page, I'm getting a 500 error "Session has not been configured for this application or request"...?

- Mike

@Joel,

What you report sounds like a bug. Remember that the framework is still in Beta. Nevertheless, you shouldn't really be setting or getting session variables in a ViewStart file.

- Hisham Abdullah Bin Ateya

Thanks Mike for sharing this article. George it will be nice if we let the web developers implement an interface T <-> byte[] ,but you are welcome to share your suggestions in the thread that I already started in the session repo.

- vamsi

good article

- Magnus

One thing that took me a while to figure out, is that the UseSession() must come before UseMVC() in the startup file.

I was looking at an InvalidException in my Context class, when I had put it the other way around.

- Hisham Abdullah Bin Ateya

FYI the Session.GetInt & Context.Session.SetInt have been renamed to Context.Session.GetInt32 & Context.Session.SetInt32

- Mike

@Hisham,

Thanks - I'll update the article when the next CTP is released.

- Dan

Can I ask how these sort of options are affected by the IIS configuration options when hosted in IIS. Will they be ignored, will the options be disabled??

- Mike

@Dan,

Session in ASP.NET 5 is not dependent on IIS in any way. There's nothing in the source code that refers to IIS settings so they will have no effect on your configuration. I have no idea how or if the IIS team will change any part of their management tools to cater for ASP.NET 5.

- frank

Mike can you write up an article showcasing the difference / upgrade paths of ASP.net Web Pages and New MVC 6? The reason I ask, is now these two are in the same boat, but there is next to ZERO documentation on the new Web Pages, and how they can live with MVC

THANKS

- Mike

@frank,

There is no documentation on the new Web Pages framework at the moment because the framework doesn't exist. I am told that a new Web Pages framework will definitely be introduced in ASP.NET 5, but not until after the RTM. Then it should make the first release after that. When there is something to write about, I will most certainly produce some articles.

- prakash

Nice article..thank you....

- Piotrek

Hi,
it seems it doesn't work now. When I use UseInMemorySession, it throws this error: "IApplicationBuilder does not contain definiotion of UseInMemorySession".

I solved it thanks for http://stackoverflow.com/questions/32250659/using-sessions-in-asp-net-5-mvc-6 , but it still doesn't work because I get another error: "the best overload for UseSession does not have parameter configure".

How can I fix it?

- John A Davis

I am so glad I found your blog or whatever you call it. I can see I'm gonna have hours of good stuff to read. Your Net 5 stuff is quickly making me an expert here where I work. Thank you very much.

Someone at MS really should make multiple checkboxes easier to implement. Everyone needs them and checkboxes have always been a bain.

- Alex Logan

Hi Mike.

It might be useful to know that in order to access the context outside a controller, you can inject IHttpContextAccessor into your class.

Recent Comments

Obinna Okafor 26/05/2017 16:16
In response to Razor Pages - The Elevator Pitch
Thank you for this wonderful piece, Mike. I need more of these...Keep them coming - anything more...

Cyrus 26/05/2017 06:00
In response to Razor Pages - The Elevator Pitch
There are some concern about razor pages performance. Is it faster or slower than MVC? would you a a...

Cyrus 26/05/2017 05:44
In response to Razor Pages - Understanding Handler Methods
well done, thank you....

Satyabrata Mohapatra 23/05/2017 11:41
In response to Razor Pages - Understanding Handler Methods
Nice and easy !! Great post....

Cyrus 16/05/2017 19:55
In response to Razor Pages - Getting Started With The Preview
There is something wrong related to microsoft.dotnetcore.mvc.taghelpers! if you remove it from page...

Cyrus 16/05/2017 10:18
In response to Razor Pages - Getting Started With The Preview
well done mike, it was very useful, I really appreciate that....

Satyabrata Mohapatra 16/05/2017 07:21
In response to Razor Pages - Getting Started With The Preview
Finally!!!! web pages in asp.net core!!! Super excited !!!! Thank u sir for sharing.....Awaiting on...

Daniele 14/03/2017 10:24
In response to Working With Zip Files In ASP.NET MVC
is it possible give to the user a progress bar of the zipping process? Thanks in advance. ...

Suraj 13/03/2017 22:20
In response to Working With Zip Files In ASP.NET MVC
Very nice article. Thanks....

Satyabrata Mohapatra 19/02/2017 03:01
In response to Free SSL Certificates On IIS With LetsEncrypt
Thanks for sharing. Learned a lot !!...