¿Cómo usar sesiones en una aplicación ASP.NET MVC 4?

113

Soy nuevo en ASP.NET MVC. He usado PHP antes y fue fácil crear una sesión y seleccionar registros de usuario en función de las variables de la sesión actual.

He buscado en todas partes de Internet un sencillo tutorial paso a paso que pueda mostrarme cómo crear y usar sesiones en mi aplicación C # ASP.NET MVC 4. Quiero crear una sesión con variables de usuario a las que pueda acceder desde cualquier lugar de mis controladores y poder usar las variables en mis consultas LINQ.

Thuto Paul Gaotingwe
fuente
2
posible duplicado de Cómo mantener la sesión de usuario con ASP.NET MVC
adatapost
2
Este artículo podría ser de interés: brockallen.com/2012/04/07/think-twice-about-using-session-state
Daniel Hollinrake

Respuestas:

160

Tratar

//adding data to session
//assuming the method below will return list of Products

var products=Db.GetProducts();

//Store the products to a session

Session["products"]=products;

//To get what you have stored to a session

var products=Session["products"] as List<Product>;

//to clear the session value

Session["products"]=null;
Jobert Enamno
fuente
3
¡Gracias Jobert! me diste una idea! Sin embargo, me pregunto ... ¿es posible agregar variables de usuario a una sesión durante el inicio de sesión? y también tendré acceso a variables de sesión (creadas solo una vez) en diferentes controladores en mi aplicación?
Thuto Paul Gaotingwe
31
Puede almacenar cualquier cosa o cualquier dato de cualquier tipo en una sesión. Una vez creado, puede acceder al valor almacenado en todas las vistas y controladores. Tenga en cuenta también que la sesión creada solo es accesible por usuario y por navegador. Lo que significa que el mismo usuario que usa IE no puede acceder a la sesión creada por User1 usando Firefox. También hay cosas que no debe hacer con la sesión, como. NO almacene grandes datos en él. Esto puede ralentizar el rendimiento de su servidor. Por último, NO almacene datos confidenciales en una sesión como la contraseña o el número de tarjeta de crédito
Jobert Enamno
2
¡Gracias una vez más! ¿Dónde lo creo para poder acceder a él a través de diferentes controladores?
Thuto Paul Gaotingwe
2
@JobertEnamno, ¿es seguro almacenar el valor del que proviene WebSecurity.CurrentUserIdpara que no lo extraiga de la base de datos varias veces (descubrí que es muy costoso)?
Andrius Naruševičius
2
No hay una sesión de controlador cruzado, por lo que cuando solicita otro controlador, por ejemplo, de Account/LogOna Home/Index, Session["FirstName"]es null. Los desarrolladores deben crear un controlador principal ( BaseController) y definir un campo protegido ( internal protected HttpSessionStateBase SharedSession) que puede exponer la variable de sesión compartida en todos los subcontroladores (esto supone que todos los controladores de su aplicación heredan del BaseController)
Bellash
63

Debido a la naturaleza sin estado de la web, las sesiones también son una forma extremadamente útil de persistir objetos en las solicitudes serializándolos y almacenándolos en una sesión.

Un caso de uso perfecto de esto podría ser si necesita acceder a información regular a través de su aplicación, para guardar llamadas de base de datos adicionales en cada solicitud, estos datos se pueden almacenar en un objeto y no serializar en cada solicitud, así:

Nuestro objeto serializable y reutilizable:

[Serializable]
public class UserProfileSessionData
{
    public int UserId { get; set; }

    public string EmailAddress { get; set; }

    public string FullName { get; set; }
}

Caso de uso:

public class LoginController : Controller {

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            var profileData = new UserProfileSessionData {
                UserId = model.UserId,
                EmailAddress = model.EmailAddress,
                FullName = model.FullName
            }

            this.Session["UserProfile"] = profileData;
        }
    }

    public ActionResult LoggedInStatusMessage()
    {
        var profileData = this.Session["UserProfile"] as UserProfileSessionData;

        /* From here you could output profileData.FullName to a view and
        save yourself unnecessary database calls */
    }

}

Una vez que este objeto ha sido serializado, podemos usarlo en todos los controladores sin necesidad de crearlo o consultar la base de datos para obtener los datos que contiene nuevamente.

Inyecte su objeto de sesión usando Dependency Injection

En un mundo ideal, ' programaría en una interfaz, no en una implementación ' e inyectaría su objeto de sesión serializable en su controlador usando su contenedor de Inversión de Control de su elección, así (este ejemplo usa StructureMap ya que es con el que estoy más familiarizado ).

public class WebsiteRegistry : Registry
{
    public WebsiteRegistry()
    {
        this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());   
    }

    public static IUserProfileSessionData GetUserProfileFromSession()
    {
        var session = HttpContext.Current.Session;
        if (session["UserProfile"] != null)
        {
            return session["UserProfile"] as IUserProfileSessionData;
        }

        /* Create new empty session object */
        session["UserProfile"] = new UserProfileSessionData();

        return session["UserProfile"] as IUserProfileSessionData;
    }
}

Luego registraría esto en su Global.asax.csarchivo.

Para aquellos que no están familiarizados con la inyección de objetos de sesión, pueden encontrar una publicación de blog más detallada sobre el tema aquí .

Una palabra de advertencia:

Vale la pena señalar que las sesiones deben mantenerse al mínimo, las sesiones grandes pueden comenzar a causar problemas de rendimiento.

También se recomienda no almacenar ningún dato sensible en ellos (contraseñas, etc.).

Joseph Woodward
fuente
¿Dónde pondrías la definición de clase? Todavía soy bastante nuevo en todo, pero solo tengo curiosidad sobre cómo otros controladores verán la clase y sabrán qué es. ¿Lo agrega a la parte superior del controlador? Estaba pensando en SessionStart en global.asax. Inicializaría las cosas, pero tal vez esa no sea la mejor manera de hacerlo.
Shaun314
@ Shaun314 Idealmente, usaría un contenedor de IoC para inyectar el objeto en su controlador a través de la inyección de dependencia (ver editar).
Joseph Woodward
1
Estoy almacenando información de sesión después de iniciar sesión como usuario usando Identity 2. No puedo recuperar esa información en otras acciones y controladores que no sean la primera acción a la que redirecciono al usuario. ¿Alguna idea?
Akbari
17

Así es como funciona el estado de la sesión en ASP.NET y ASP.NET MVC:

Descripción general del estado de sesión de ASP.NET

Básicamente, haces esto para almacenar un valor en el objeto Session:

Session["FirstName"] = FirstNameTextBox.Text;

Para recuperar el valor:

var firstName = Session["FirstName"];
Leniel Maccaferri
fuente
10
No hay una sesión de controlador cruzado, por lo que cuando solicita otro controlador, por ejemplo, de Accounta Home, la sesión ["Nombre"] es nula. Los desarrolladores deben crear BaseControllery definir un campo protegido ( internal protected HttpSessionStateBase SharedSession) que pueda exponer la Sessionvariable compartida en todos los subcontroladores (esto supone que todos los controladores de su aplicación heredan del BaseController)
Bellash
4
Umm, ¿seguro que lo hay? Hay una variable de sesión en Controller (el controlador base proporcionado por MVC).
aeliusd
7
@Bellash esto está completamente mal. Las sesiones están disponibles en todos los controladores. Simplemente configuro Session ["test"] en HomeController y luego lo leo en mi AccountController.
niico
0

Puede almacenar cualquier tipo de datos en una sesión usando:

Session["VariableName"]=value;

Esta variable tendrá una duración de 20 minutos aproximadamente.

Ulises
fuente
-8

U puede almacenar cualquier valor en la sesión como Session ["FirstName"] = FirstNameTextBox.Text; pero te sugeriré que lo tomes como campo estático en el modelo y que puedas acceder a ese valor de campo en cualquier lugar de la aplicación. No necesitas sesión. debe evitarse la sesión.

public class Employee
{
   public int UserId { get; set; }
   public string EmailAddress { get; set; }
   public static string FullName { get; set; }
}

en el controlador - Employee.FullName = "ABC"; Ahora puede acceder a este nombre completo en cualquier lugar de la aplicación.

Mukul Sharma
fuente
10
El almacenamiento de datos en campos estáticos, especialmente datos de usuario como el nombre del empleado, provocará problemas graves en entornos de múltiples usuarios. Cuando dos usuarios diferentes inician sesión en el sistema, verán el mismo Employee.EmailAddress ya que el campo estático en Employee es el mismo para cada instancia.
Gökçer Gökdal