I generally use this for a session key and then explicitly add objects as needed. The reason for this is it's a clean way to do it and I find that you want to keep the number of objects in session to a minimum.
This particular approach brings together forms authentication and user session into one place so you can add objects and forget about it. The argument could be made that it is a big verbose, but it does prevent any double up and you shouldn't have too many objects in session.
The following can exist in a core library or wherever you want.
/// <summary>
/// Provides a default pattern to access the current user in the session, identified
/// by forms authentication.
/// </summary>
public abstract class MySession<T> where T : class
{
public const string USERSESSIONKEY = "CurrentUser";
/// <summary>
/// Gets the object associated with the CurrentUser from the session.
/// </summary>
public T CurrentUser
{
get
{
if (HttpContext.Current.Request.IsAuthenticated)
{
if (HttpContext.Current.Session[USERSESSIONKEY] == null)
{
HttpContext.Current.Session[USERSESSIONKEY] = LoadCurrentUser(HttpContext.Current.User.Identity.Name);
}
return HttpContext.Current.Session[USERSESSIONKEY] as T;
}
else
{
return null;
}
}
}
public void LogOutCurrentUser()
{
HttpContext.Current.Session[USERSESSIONKEY] = null;
FormsAuthentication.SignOut();
}
/// <summary>
/// Implement this method to load the user object identified by username.
/// </summary>
/// <param name="username">The username of the object to retrieve.</param>
/// <returns>The user object associated with the username 'username'.</returns>
protected abstract T LoadCurrentUser(string username);
}
}
Then implement this in the following class namespaced to the root of your project (I usually put it in a code folder on mvc projects):
public class CurrentSession : MySession<PublicUser>
{
public static CurrentSession Instance = new CurrentSession();
protected override PublicUser LoadCurrentUser(string username)
{
// This would be a data logic call to load a user's detail from the database
return new PublicUser(username);
}
// Put additional session objects here
public const string SESSIONOBJECT1 = "CurrentObject1";
public const string SESSIONOBJECT2 = "CurrentObject2";
public Object1 CurrentObject1
{
get
{
if (Session[SESSIONOBJECT1] == null)
Session[SESSIONOBJECT1] = new Object1();
return Session[SESSIONOBJECT1] as Object1;
}
set
{
Session[SESSIONOBJECT1] = value;
}
}
public Object2 CurrentObject2
{
get
{
if (Session[SESSIONOBJECT2] == null)
Session[SESSIONOBJECT2] = new Object2();
return Session[SESSIONOBJECT2] as Object2;
}
set
{
Session[SESSIONOBJECT2] = value;
}
}
}
FINALLY
The big advantage of explicitly declaring what you want in session is that you can reference this absolutely anywhere in your mvc application including the views. Just reference it with:
CurrentSession.Instance.Object1
CurrentSession.Instance.CurrentUser
Again a little less generic than other approaches, but really really clear what's going on, no other rigging or dependancy injection and 100% safe to the request context.
On another note, the dicionary approaches are cool, but you still end up with strings all over the place to reference stuff. You could rig it with enums or something, but I prefer the strong typing and set and forget of the above approach.
_T
? Why not justT
? – Shores