Problem
How to store data in session state using ASP.NET Core.
Solution
Using an empty project from a previous post, amend Startup
class ConfigureServicee()
method, add services for session and its backing store:
1 2 3 4 5 6 |
public void ConfigureServices( IServiceCollection services) { services.AddDistributedMemoryCache(); services.AddSession(); } |
Add the session middleware in Configure()
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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 mintues.
1 2 3 4 5 6 7 8 9 10 11 12 |
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 serialise objects into JSON strings to achieve this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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
.
Source Code
GitHub: https://github.com/TahirNaushad/Fiver.Asp.SessionState