We had a similar scenario where we wanted to store login information about the current user from the session. However, we opted out of directly storing it on top of the session object, and we detached ourselves from the expiration mechanism of the session, so we only depend on the session ID that the request bears.
What we did was create a custom cache which contains information about the users, identified by the session ID (which is a GUID, thus having astronomically close to 0% chance of collisions). That cache is a ConcurrentDictionary<string, UserInformationModel>
instance, with string
being the session ID token, and UserInformationModel
being a model with all the information a user might have on their current session, including credentials, state, cached profile information, etc.
Note that the above approach closely resembles that of a god model, but it acts as the root of all the information a user bears in their current session.
That dictionary is periodically cleaned with a custom mechanism that iterates through all the current sessions asynchronously and removes the expired entries. We expire entries based on our own rules, they are only alive for 15 minutes since their creation, and never extend the lifetime. Expired entries are never returned if they are expired, even if the session ID is still alive.
We still want to return information about a specific user during the cleanup of the expired entries. We make sure that we never return expired information, and that we can always fall back to re-instantiating a new instance for the same session ID, depending on the expiration state.
To make this all work, and since we do not store any information on the Session
object of the HttpContext
, we store a dummy value set to 1 just to cause ASP.NET Core to preserve the Session
object and its ID. In the documentation it notes that if the session carries no information, it is immediately discarded, hence the above workaround.
Thus, we have a system that relies on the automatically generated session IDs of ASP.NET Core, but store our information in a custom in-memory cluster that cleans itself up periodically and prevents invalidated data from being used.
For your case, you might try some similar structure out. It will definitely help since you are storing several fields about a user, which user you effectively identify via a session object.
Also, the greatest deal of all this is that you have a root object that provides access to the fields of your interest without knowing about the names of the fields in a name-value dictionary. It helps you be certain that those fields are not ghosts and have a commonly shared model across the entirety of your application that involves user information.
P.S. You mention you use .NET Framework 4.8, thus not ASP.NET Core. However, the same approach can be easily applied in ASP.NET, as you are still provided with a session object on the HttpContext
object of each request you are handling.