Problem
How to store data in session state using ASP.NET Core.
Solution
Using an empty project from a previous post, amend Startup
class ConfigureServices()
method, add services for session and its backing store:
public void ConfigureServices(
IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession();
}
Add the session middleware in Configure()
method:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
app.UseSession();
app.Use(async (context, next) =>
{
context.Session.SetString("GreetingMessage", "Hello Session State");
await next();
});
app.Run(async (context) =>
{
var message = context.Session.GetString("GreetingMessage");
await context.Response.WriteAsync($"{message}");
});
}
Discussion
We can use session in order to share information between different HTTP requests coming from a single browser. The data is stored in a cache (IDistributedCache
implementation to be specific) and accessed via HttpContext.Session
property.
A cookie is stored in browser to correlated the HTTP requests. The default name of this cookie is .AspNet.Session
.
During the configuration of session services, we can set various properties:
HttpOnly
: Sets whether cookie is accessible through JavaScript. Default is true
, which means it can’t be accessed via scripts on the client-side. Name
: Used to override the default cookie name. SecurePolicy
: Determines if session cookie is only transmitted via HTTPS requests. IdleTimeout
: Sets the time for session expiry, each request resets the timeout. Default is 20 minutes.
public void ConfigureServices(
IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.Name = ".Fiver.Session";
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.IdleTimeout = TimeSpan.FromMinutes(10);
});
}
Storing Objects
HttpContext.Session
(or ISession
that it implements) does not provide a built-in way to store complex objects, however, we can serialize objects into JSON string
s to achieve this:
public static class SessionExtensions
{
public static void SetObject<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObject<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default(T) :
JsonConvert.DeserializeObject<T>(value);
}
}
Now we can use these extension methods like below:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseSession();
app.Use(async (context, next) =>
{
context.Session.SetObject("CurrentUser",
new UserInfo { Username = "James", Email = "james@bond.com" });
await next();
});
app.Run(async (context) =>
{
var user = context.Session.GetObject<UserInfo>("CurrentUser");
await context.Response.WriteAsync($"{user.Username}, {user.Email}");
});
}
Accessing via Dependency Injection
To access session using dependency injection, you could use IHttpContextAccessor
(via constructor), which gives you access to HttpContext
.