Generalmente uso esto para una clave de sesión y luego agrego objetos explícitamente según sea necesario. La razón de esto es que es una manera limpia de hacerlo y me parece que desea mantener el número de objetos en sesión al mínimo.
Este enfoque particular reúne autenticación de formularios y sesión de usuario en un solo lugar para que pueda agregar objetos y olvidarse de ellos. Se podría argumentar que es un gran verbo, pero previene cualquier duplicación y no debería haber demasiados objetos en sesión.
Lo siguiente puede existir en una biblioteca central o donde lo desee.
/// <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);
}
}
Entonces implementar esto en la siguiente clase de espacio de nombres a la raíz de su proyecto (por lo general lo puso en una carpeta de código en proyectos MVC):
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;
}
}
}
FINALMENTE La gran ventaja de declarar de manera explícita lo que desea en la sesión es que puede hacer referencia a esto absolutamente en cualquier lugar de la aplicación mvc, incluidas las vistas. Simplemente hacer referencia a ella con:
CurrentSession.Instance.Object1
CurrentSession.Instance.CurrentUser
de nuevo un poco menos genérico que otros enfoques, pero muy, muy claro lo que está pasando, ningún otro aparejo o inyección de dependencias y 100% seguro para el contexto de la petición.
En otro aspecto, los enfoques dicionarios son geniales, pero todavía terminas con cadenas por todo el lugar para hacer referencia a cosas. Puede equiparlo con enumeraciones o algo así, pero prefiero la tipificación fuerte y establecer y olvidar el enfoque anterior.
¿Qué pasará si pasa el mismo tipo a más de un controlador? Una sesión sobrescribirá la otra? –
No, ambos tendrán el mismo nombre y, por lo tanto, la misma clave de sesión. Los objetos de la sesión no serán reemplazados, solo serán el mismo objeto en ambos controladores. –
Respuesta agregada a continuación que no requiere controladores base y que incluso puede acceder a la sesión en el código de vista también. – Gats