ASP.NET Core MVC – Start session extension modularized

I got a feature request that I should store something on session start. In the old ASP.NET Framework world it was easy because we had Globbal.asax.cs and its Session_Start event. The original answer to this question is here. But, as I prefer overengineering modular architecture and Sitecore Helix principles I wanted to make it extensible without touching this Foundation piece of code. As you probably know we have Startup.cs instead of Global.asax.cs and DistributedSessionStore. To extend the Create method of the DistributedSessionStore you can just simply inherit from its interface ISessionStore.

public class DistributedSessionStoreWithStart : DistributedSessionStore, ISessionStore
{
readonly IStartSession _startSession;
public DistributedSessionStoreWithStart(
IDistributedCache cache,
ILoggerFactory loggerFactory,
IStartSession startSession)
: base(cache, loggerFactory)
{
_startSession = startSession;
}
public new ISession Create(
string sessionKey,
TimeSpan idleTimeout,
TimeSpan ioTimeout,
Func<bool> tryEstablishSession,
bool isNewSessionKey)
{
var session = base.Create(sessionKey, idleTimeout, ioTimeout, tryEstablishSession, isNewSessionKey);
if (isNewSessionKey)
{
_startSession.InvokeStartSesssionActions(session);
}
return session;
}
}

As its seen above I have implemented a custom interface which contains all the actions I want to call on Create. These 2 classes lays in the Foundation layer if you follow Sitecore Helix principles.

public interface IStartSession
{
void InvokeStartSesssionActions(ISession session);
void AddToStartSession(Action<ISession> action);
}
public class StartSession : IStartSession
{
private static readonly IList<Action<ISession>> StartSessionActions = new List<Action<ISession>>();
public void InvokeStartSesssionActions(ISession session)
{
foreach (var action in StartSessionActions)
{
action.Invoke(session);
}
}
public void AddToStartSession(Action<ISession> action)
{
StartSessionActions.Add(action);
}
}
view raw StartSession.cs hosted with ❤ by GitHub

As a last but one, a SessionExtensions (lays in the Foundation layer as well) implemented to put together the configuration of the session in one place:

public static class SessionExtensions
{
public static void AddSessionWithStartSession(this IServiceCollection services)
{
services.AddSingleton<ISessionStore, DistributedSessionStoreWithStart>();
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.Cookie.IsEssential = true;
});
services.AddSingleton<IStartSession>(s =>
{
var startSession = new StartSession();
// Add here other actions if more funcionality is needed for session start
startSession.AddToStartSession(s.GetRequiredService<IUrlRefererService>().SetSessionStartRefererUrl);
return startSession;
});
}
}

As a last step call this method in the ConfigureServices method and setup the application to use session – this lays in the Project layer.

public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSessionWithStartSession();
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseSession();
...
}
...
}
view raw Startup.cs hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s