¿Cómo acceder a las variables de sesión desde cualquier clase en ASP.NET?

157

He creado un archivo de clase en la carpeta App_Code en mi aplicación. Tengo una variable de sesión

Session["loginId"]

Quiero acceder a las variables de esta sesión en mi clase, pero cuando escribo la siguiente línea, aparece un error

Session["loginId"]

¿Alguien puede decirme cómo acceder a las variables de sesión dentro de una clase que se crea en la carpeta app_code en ASP.NET 2.0 (C #)

Prasante
fuente

Respuestas:

363

(Actualizado para completar)
Puede acceder a las variables de sesión desde cualquier página o control usando Session["loginId"]y desde cualquier clase (por ejemplo, desde dentro de una biblioteca de clases), usandoSystem.Web.HttpContext.Current.Session["loginId"].

Pero sigue leyendo para obtener mi respuesta original ...


Siempre uso una clase contenedora alrededor de la sesión ASP.NET para simplificar el acceso a las variables de sesión:

public class MySession
{
    // private constructor
    private MySession()
    {
      Property1 = "default value";
    }

    // Gets the current session.
    public static MySession Current
    {
      get
      {
        MySession session =
          (MySession)HttpContext.Current.Session["__MySession__"];
        if (session == null)
        {
          session = new MySession();
          HttpContext.Current.Session["__MySession__"] = session;
        }
        return session;
      }
    }

    // **** add your session properties here, e.g like this:
    public string Property1 { get; set; }
    public DateTime MyDate { get; set; }
    public int LoginId { get; set; }
}

Esta clase almacena una instancia de sí misma en la sesión ASP.NET y le permite acceder a las propiedades de su sesión de forma segura desde cualquier clase, por ejemplo, así:

int loginId = MySession.Current.LoginId;

string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;

DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;

Este enfoque tiene varias ventajas:

  • te salva de muchos tipos de fundición
  • no tiene que usar claves de sesión codificadas en toda su aplicación (por ejemplo, Sesión ["loginId"]
  • puede documentar los elementos de su sesión agregando comentarios de documentos XML en las propiedades de MySession
  • puede inicializar sus variables de sesión con valores predeterminados (por ejemplo, asegurarse de que no sean nulos)
M4N
fuente
66
No es necesario escribir ningún código, use como se muestra en la respuesta. Por ejemplo, "public int LoginId {get; set;}" -> esto se llama una propiedad automática.
M4N, el
44
Si está usando .net 3.x puede usar propiedades automáticas como se muestra en mi código. Con .net 2.x / 1.x esto no está disponible y tiene que implementar el getter / setter de sus propiedades usted mismo: private int _loginId; public int LoginId {get {return _loginId; } establecer {_loginId = valor; }}
M4N
2
Parece genial ahora, creo que obtuve la respuesta de mi problema, y ​​ya estoy usando tu camino, es muy limpio y fácil de mantener todas mis variables de sesión en un solo lugar. Gracias @ Martin, eres IMPRESIONANTE.
Prashant
23
@ M4N, desearía poder expresar un poco más de gratitud que un +1. Esta se ha convertido en mi forma favorita de tratar con la sesión / caché en mis proyectos. Mi código, literalmente, te está agradeciendo.
Brandon Boone
44
@Kristopher, mientras que la propiedad 'Actual' es estática, la instancia de MySession devuelta no lo es ... así que está bien. Los métodos y propiedades estáticos son seguros de usar de esta manera.
Darren
104

Acceda a la sesión a través de los hilos HttpContext: -

HttpContext.Current.Session["loginId"]
AnthonyWJones
fuente
Muchas gracias Anthony por este simple paso.
Reyes
Muchas gracias Anthony, + 1 por eso
Owais Qureshi
Gracias. Olvidé cuál era el espacio de nombres :)
Anthony Horne
@AnthonyWJones Usé tu método, pero tengo un problema, ¿puedes explicarme dónde estoy equivocado o cuál es la forma correcta de usarlo? Mi pregunta stackoverflow.com/questions/45254279/…
adnan
y si desea convertir a HttpSessionStateBase: HttpSessionStateBase session = new HttpSessionStateWrapper (HttpContext.Current.Session); re: stackoverflow.com/questions/5447611/…
sobelito
24

El problema con la solución sugerida es que puede romper algunas características de rendimiento integradas en SessionState si está utilizando un almacenamiento de sesión fuera de proceso. ("Modo de servidor de estado" o "Modo de servidor SQL"). En los modos oop, los datos de la sesión deben ser serializados al final de la solicitud de página y deserializados al comienzo de la solicitud de página, lo que puede ser costoso. Para mejorar el rendimiento, SessionState intenta solo deserializar lo que se necesita solo deserializar la variable cuando se accede por primera vez, y solo vuelve a serializar y reemplaza la variable que se modificó. Si tiene muchas variables de sesión y las inserta en una sola clase, esencialmente todo en su sesión se deserializará en cada solicitud de página que use la sesión y todo deberá ser serializado nuevamente, incluso si solo se modificó 1 propiedad porque la clase cambió. Solo algo a tener en cuenta si estás usando mucha sesión y un modo oop.

Ernie
fuente
44
+1 por aclarar esto. Si no está utilizando InProc para la sesión, Ernie es 100% correcto. InProc es muy limitado de todos modos, ya que no admite webfarms y se perderá si la aplicación se reinicia. Tenga en cuenta que, por el costo de rendimiento, estamos viendo una prima del 20% al usar el modo Servidor de estado, y además se agregan los costos de serialización. Como puedes imaginar, esto puede ser costoso. Puede evitar parte de la sobrecarga de serialización si se adhiere a los tipos primitivos (por ejemplo, int, string, char, byte, etc.). Los objetos personalizados se enfrentarán a la serialización. Cuidado con el usuario.
Zack Jannsen
+1 Buen punto. Un cambio que uniría los dos conceptos sería que cada propiedad de esta clase de "sesión" personalizada llamara a la sesión asp.net en lugar de un objeto grande en la sesión. Tiene que hacer el tipo de conversión que evita el enfoque de @ M4N, pero tal vez valga la pena si solo lee parte de la sesión cada vez.
eol
12

Las respuestas presentadas antes que las mías proporcionan soluciones adecuadas al problema, sin embargo, creo que es importante entender por qué se produce este error:

La Sessionpropiedad de Pagedevuelve una instancia de tipo en HttpSessionStaterelación con esa solicitud en particular. Page.Sessionen realidad es equivalente a llamar Page.Context.Session.

MSDN explica cómo esto es posible:

Como las páginas ASP.NET contienen una referencia predeterminada al espacio de nombres System.Web (que contiene la HttpContextclase), puede hacer referencia a los miembros de HttpContextuna página .aspx sin la referencia de clase totalmente calificada HttpContext.

Sin embargo, cuando intente acceder a esta propiedad dentro de una clase en App_Code, la propiedad no estará disponible para usted a menos que su clase se derive de la Clase de página.

Mi solución a este escenario frecuente es que nunca paso objetos de página a clases . Preferiría extraer los objetos requeridos de la página Sesión y pasarlos a la Clase en forma de una colección de valores de nombre / Array / List, según el caso.

Cerebro
fuente
Esa es una gran explicación, me ayudó +1 para eso :)
Owais Qureshi
1

Tuve el mismo error, porque estaba tratando de manipular las variables de sesión dentro de una clase de sesión personalizada.

Tuve que pasar el contexto actual (system.web.httpcontext.current) a la clase, y luego todo salió bien.

MAMÁ

MunsterMan
fuente
1

En asp.net core esto funciona de manera diferente:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

Fuente: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/

Matty
fuente
0

Esto debería ser más eficiente tanto para la aplicación como para el desarrollador.

Agregue la siguiente clase a su proyecto web:

/// <summary>
/// This holds all of the session variables for the site.
/// </summary>
public class SessionCentralized
{
protected internal static void Save<T>(string sessionName, T value)
{
    HttpContext.Current.Session[sessionName] = value;
}

protected internal static T Get<T>(string sessionName)
{
    return (T)HttpContext.Current.Session[sessionName];
}

public static int? WhatEverSessionVariableYouWantToHold
{
    get
    {
        return Get<int?>(nameof(WhatEverSessionVariableYouWantToHold));
    }
    set
    {
        Save(nameof(WhatEverSessionVariableYouWantToHold), value);
    }
}

}

Aquí está la implementación:

SessionCentralized.WhatEverSessionVariableYouWantToHold = id;
Capitan America
fuente