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).
Enabling Session State
Session management in ASP.NET Core is included in the Microsoft.AspNetCore.All
metapackage, but is not enabled by default. You enable Session State in the Startup file:
public void ConfigureServices(IServiceCollection services)
{
services.AddSession();
services.AddMemoryCache();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
}
Note the use of the AddMemoryCache
method in ConfigureServices
. Session data needs a store. AddMemoryCache
activates a local memory-based store, which is fine for most applications deployed to a single server. They are volatile, and can be cleared out by processes external to your site (server restarts, application pool recycling etc) so you should always test for the presence of your expected values. If your site is to be deployed to multiple servers, you should use a distributed cache implementation instead. Distributed caches use a centralised data store to ensure that the same values are available to all application servers. The SQL Server Distributed cache system uses a SQL Server database. Other systems may use memory, like the open source Redis and Memcached solutions.
Configuring Sessions
Once enabled, a session begins when the user first visits the site, and lasts for 20 minutes after the last activity from the user at which point the contents of the session are abandoned. The duration is controlled by the IdleTimeout
option, which can be configured in ConfigureServices
:
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(30);
});
Every time the session is accessed, the timeout is reset.
Another option related to timeouts is the IOTimeout
option. This controls the maximum amount of time to allow for the successful getting or setting of a session asynchronously, and is therefore applicable mainly to the use of distributed caches. The default value is 1 minute.
Using Session Variables
The Session API offers three methods for setting session values: SetInt32
, SetString
and Set
, which takes a byte
array as an argument. The session framework stores items as byte arrays to ensure that session values are serialisable, primarily for storage on remote servers. Internally, the SetInt
and SetString
methods convert the supplied values to a byte
array. Here is the actual implementation of the SetString
method:
public static void SetString(this ISession session, string key, string value)
{
session.Set(key, Encoding.UTF8.GetBytes(value));
}
See the AspNet/HttpAbstractions Repo for more details
You need to add a reference to Microsoft.AspNetCore.Http
to be able to work with session. The following examples illustrate various ways to set session values:
public void OnGet()
{
HttpContext.Session.SetString("Test String", "1");
HttpContext.Session.SetInt32("Test Int", 1);
HttpContext.Session.Set("Test Byte Array", BitConverter.GetBytes(true)); // boolean as byte array
}
And here's how you might retrieve those values to be passed to a View:
public void OnPost()
{
ViewData["Test String"] = HttpContext.Session.GetString("Test String");
ViewData["Test Int"] = HttpContext.Session.GetInt32("Test Int");
ViewData["Test Byte Array"], BitConverter.ToBoolean(HttpContext.Session.Get("Test Byte Array"), 0);
}
All of the Get
method along with the GetString
and GetInt32
methods return null
if no value has been set for the referenced key, or if the value has been cleared for any reason. If that happens to the Test Byte Array
value, the BitConverter.ToBoolean
method call will result in an ArgumentNullException
. You should test for this before attempting any further operations:
public void OnPost()
{
if(HttpContext.Session.Get("Test Byte Array") != null)
{
ViewData["Test Byte Array"], BitConverter.ToBoolean(HttpContext.Session.Get("Test Byte Array"), 0);
}
}
You can also use the TryGetValue
method to achieve the same result in a cleaner way:
public void OnPost()
if (HttpContext.Session.TryGetValue("Test Byte Array", out byte[] result))
{
ViewData["Test Byte Array"] = BitConverter.ToBoolean(result, 0);
}
Working with other types
As has been shown, when setting non-string or int values values as session variables, you need to take care of serialisation to byte arrays yourself. You could do this at the point of setting values as illustrated earlier, but a more reusable approach can be achieved by creating your own extension methods on ISession
. The following example shows how you might implement methods for getting and setting boolean values as session variables:
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 to set and get boolean values:
public void OnGet()
{
HttpContext.Session.SetString("Test String", "1");
HttpContext.Session.SetInt32("Test Int", 1);
HttpContext.Session.SetBoolean("Test Bool", true);
}
public void OnPost()
{
ViewData["Test String"] = Name = HttpContext.Session.GetString("Test String");
ViewData["Test Int"] = HttpContext.Session.GetInt32("Test Int");
ViewData["Test Bool"] = HttpContext.Session.GetIntBoolean("Test Bool");
}
There are two methods of interest if you want to delete session values. One is the Remove
method which allows you to delete individual values from the session collection by key:
HttpContext.Session.Remove("Name");
The other is the Clear
method. This removes all keys and values associated with the session:
HttpContext.Session.Clear();
Session Cookies
ASP.NET Core uses cookies to tie multiple request together in a session. The cookie options are managed using the Options pattern when configuring sessions:
public void ConfigureServices(IServiceCollection services)
{
services.AddSession(options => {
options.Cookie.Name = "MySessionCookie";
});
}
The full list of properties is as follows:
Property | Data Type | Description |
---|---|---|
Domain |
string |
The domain(s) that the cookie is accessible to. If it is not specified, the cookie is only sent to the domain of the current document. If provided, all sub-domains are also included. |
Expiration |
TimeSpan |
The expiry time. While it is (currently possible)[https://github.com/aspnet/Security/issues/1293] to set an expiry time for the session cookie, you are advised not to. Session cookies should only last for the duration of the session as governed by the IdleTimeout setting covered at the top of this article. |
HttpOnly |
bool |
Specifies whether the cookie is available to client-side code. false(the default) means that the cookie is accessible to JavaScript, which may present a security risk. If set to true, the cookie is only available to code executing on the server. |
Name |
string |
The name of the cookie. The default value is .AspNetCore.Session |
Path |
string |
The relative path that the cookie should be accessible to. If not specified, the cookie is available to all pages in the domain(s). Subdirectories are also included. For example, /account will match /account, /account/client etc. |
SameSite |
SameSiteMode enum |
Possible values are Lax (default), None , Strict . The SameSite option is intended to help in the prevention of CSRF or cookie hijacking attacks, but it is not supported by all browsers. It therefore should not be relied on. |
SecurePolicy |
CookieSecurePolicy enum |
Specifies the security policy of the cookie. Possible values are Always (Secure is always marked true ) , None (Secure is not marked true ) and SameAsRequest (The default: the cookie will be sent using the protocol of the request). |