vista tutorial net mvc modelo form entre ejemplos ejemplo diferencias controlador asp c# asp.net-mvc session strong-typing

c# - tutorial - Mejor manera de hacer sesiones de ASP.NET MVC fuertemente tipadas



web forms c# (5)

De esta manera, otros objetos no tendrán acceso a este objeto (por ejemplo, ActionFilter). Lo hago así:

public interface IUserDataStorage<T> { T Access { get; set; } } public class HttpUserDataStorage<T>: IUserDataStorage<T> where T : class { public T Access { get { return HttpContext.Current.Session[typeof(T).FullName] as T; } set { HttpContext.Current.Session[typeof(T).FullName] = value; } } }

Luego, puedo inyectar IUserDataStorage en el constructor del controlador, o usar ServiceLocator.Current.GetInstance (typeof (IUserDataStorage <T>)) dentro de ActionFilter.

public class MyController: Controller { // automatically passed by IoC container public MyController(IUserDataStorage<MyObject> objectData) { } }

Por supuesto, para los casos en que todos los controladores lo necesitan (por ejemplo, ICurrentUser), es posible que desee utilizar la inyección de propiedades en su lugar.

Estoy desarrollando un proyecto MVC de ASP.NET y quiero usar objetos de sesión fuertemente tipados. He implementado la siguiente clase derivada del controlador para exponer este objeto:

public class StrongController<_T> : Controller where _T : new() { public _T SessionObject { get { if (Session[typeof(_T).FullName] == null) { _T newsession = new _T(); Session[typeof(_T).FullName] = newsession; return newsession; } else return (_T)Session[typeof(_T).FullName]; } } }

Esto me permite definir un objeto de sesión para cada controlador, que está en línea con el concepto de aislamiento del controlador. ¿Hay alguna forma mejor / más "correcta", tal vez algo que sea oficialmente compatible con Microsoft?


Esto podría ser mejor para lo que quieres. Simplemente crearía un método de extensión que pueda acceder a su sesión. El beneficio adicional del método de extensión es que ya no tiene que heredar de un controlador, o tiene que inyectar una dependencia que realmente no es necesario para empezar.

public static class SessionExtensions { public static T Get<T>(this HttpSessionBase session, string key) { var result; if (session.TryGetValue(key, out result)) { return (T)result; } // or throw an exception, whatever you want. return default(T); } } public class HomeController : Controller { public ActionResult Index() { //.... var candy = Session.Get<Candy>("chocolate"); return View(); } }


Generalmente uso esto para una clave de sesión y luego agrego explícitamente objetos según sea necesario. La razón de esto es que es una forma limpia de hacerlo y creo que desea mantener al mínimo el número de objetos en sesión.

Este enfoque particular reúne la autenticación de formularios y la 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 detalle, pero evita que se duplique y no debería tener demasiados objetos en la sesión.

Lo siguiente puede existir en una biblioteca central o en cualquier lugar que 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); } }

Luego, implemente esto en la siguiente clase, espacio para la raíz de su proyecto (normalmente lo pongo 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 explícitamente lo que desea en una sesión es que puede hacer referencia a esto en cualquier lugar de su aplicación mvc, incluidas las vistas. Solo haz referencia con:

CurrentSession.Instance.Object1 CurrentSession.Instance.CurrentUser

De nuevo, un poco menos genérico que otros enfoques, pero realmente realmente claro lo que está pasando, no hay otro aparejo o inyección de dependencia y 100% seguro para el contexto de la solicitud.

En otra nota, los enfoques de los dictámenes son geniales, pero todavía terminas con cadenas por todas partes para hacer referencia a cosas. Podrías manipularlo con enumeraciones o algo así, pero prefiero la tipificación y configuración fuertes y olvidarme del enfoque anterior.


Sí, han pasado años desde que se hizo esta pregunta y hay otras formas de hacerlo ... pero en caso de que alguien más aparezca buscando algo que combine los enfoques anteriores en una ventanilla única atractiva (al menos una que atraiga a mi equipo y yo ...) Esto es lo que usamos.

public enum SessionKey { CurrentUser, CurrentMember, CurrentChart, CurrentAPIToken, MemberBanner } public static class SessionCache { public static T Get<T>(this HttpSessionStateBase session, SessionKey key) { var value = session[key.ToString()]; return value == null ? default(T) : (T) value; } public static void Set<T>(this HttpSessionStateBase session, SessionKey key, T item) { session[key.ToString()] = item; } public static bool contains(this HttpSessionStateBase session, SessionKey key) { if (session[key.ToString()] != null) return true; return false; } public static void clearKey(this HttpSessionStateBase session, SessionKey key) { session[key.ToString()] = null; } }

Luego, en tus controladores, puedes hacer lo tuyo con las variables de tu sesión de una manera más segura.

// get member var currentMember = Session.Get<Member>(SessionKey.CurrentMember); // set member Session.Set<Member>(SessionKey.CurrentMember, currentMember); // clear member Session.ClearKey(SessionKey.CurrentMember); // get member if in session if (Session.Contains(SessionKey.CurrentMember)) { var current = Session.Get<Member>(SessionKey.CurrentMember); }

¡Espero que esto ayude a alguien!


http://codingsmith.co.za/a-better-way-of-working-with-httpcontext-session-in-mvc/ (las disculpas por los colores de mi blog se estaban mezclando con temas y simplemente no lo he arreglado todavía)

public interface ISessionCache { T Get<T>(string key); void Set<T>(string key, T item); bool contains(string key); void clearKey(string key); T singleTon<T>(String key, getStuffAction<T> actionToPerform); } public class InMemorySessionCache : BaseSessionCache { Dictionary<String, Object> _col; public InMemorySessionCache() { _col = new Dictionary<string, object>(); } public T Get<T>(string key) { return (T)_col[key]; } public void Set<T>(string key, T item) { _col.Add(key, item); } public bool contains(string key) { if (_col.ContainsKey(key)) { return true; } return false; } public void clearKey(string key) { if (contains(key)) { _col.Remove(key); } } } public class HttpContextSessionCache : BaseSessionCache { private readonly HttpContext _context; public HttpContextSessionCache() { _context = HttpContext.Current; } public T Get<T>(string key) { object value = _context.Session[key]; return value == null ? default(T) : (T)value; } public void Set<T>(string key, T item) { _context.Session[key] = item; } public bool contains(string key) { if (_context.Session[key] != null) { return true; } return false; } public void clearKey(string key) { _context.Session[key] = null; } }

Se me ocurrió hace unos años y funciona bien. La misma idea básica que todos los demás, supongo, ¿por qué Microsoft no solo implementa esto como elude a mí?