2008-09-25 11 views
24

Quiero almacenar el "estado" de algunas acciones que el usuario está realizando en una serie de diferentes formularios web ASP.Net. ¿Cuáles son mis opciones para el estado persistente y cuáles son los pros/contras de cada solución?ASP.Net Session

He estado usando objetos de sesión, y el uso de algunos métodos de ayuda para escribir fuertemente los objetos:

public static Account GetCurrentAccount(HttpSessionState session) 
    { 
     return (Account)session[ACCOUNT]; 
    } 

    public static void SetCurrentAccount(Account obj, HttpSessionState session) 
    { 
     session[ACCOUNT] = obj; 
    } 

me han dicho por numerosas fuentes que "Sesión es malo", por lo que es realmente la causa raíz de esta pregunta. Quiero saber cuál es tu opinión sobre las "mejores prácticas" y por qué.

+1

una publicación relacionada aquí: http://stackoverflow.com/questions/769338/use-of-session-in-high-traffic-websites – MedicineMan

Respuesta

38

No hay nada inherentemente malo con el estado de la sesión.

Hay un par de cosas a tener en cuenta que pueden morder sin embargo:

  1. Si el usuario pulsa el botón atrás del navegador que vaya de nuevo a la página anterior, pero su estado de sesión no se revierte. Entonces su cuenta actual podría no ser lo que originalmente era en la página.
  2. Los procesos ASP.NET pueden ser reciclados por IIS. Cuando eso suceda, la siguiente solicitud comenzará un nuevo proceso. Si está utilizando el estado de la sesión de proceso, el valor predeterminado será :-(
  3. La sesión también puede expirar con el mismo resultado si el usuario no está activo durante un tiempo. Esto predeterminado es 20 minutos, por lo que un buen almuerzo
  4. El uso de estado de sesión fuera de proceso requiere que todos los objetos almacenados en el estado de la sesión sean serializables.
  5. Si el usuario abre una segunda ventana del navegador esperará tener una segunda aplicación distinta pero el estado de la sesión lo más probable es que se comparta entre dos. Por lo tanto, cambiar la cuenta actual en una ventana del navegador hará lo mismo en la otra.
6

En cuanto a "Session being evil" ... si estuvieras desarrollando en ASP clásico, tendría que estar de acuerdo, pero ASP.NET/IIS hace un trabajo mucho mejor.

La verdadera pregunta es cuál es la mejor manera de mantener el estado. En nuestro caso, cuando se trata del usuario con sesión iniciada, almacenamos ese objeto en Sesión, ya que estamos constantemente refiriéndonos por su nombre, dirección de correo electrónico, autorización, etc.

Otro little tidbits información que no necesita ninguna persistencia a largo plazo, utilizamos una combinación de cookies y viewstate.

10

Por lo que sé, Session es la forma prevista de almacenar esta información. Tenga en cuenta que el estado de la sesión generalmente se almacena en el proceso de forma predeterminada. Si tiene varios servidores web, o si hay un reinicio de IIS, pierde el estado de la sesión. Esto se puede solucionar utilizando un Servicio de estado ASP.NET, o incluso una base de datos SQL para almacenar sesiones. Esto garantiza que las personas recuperen su sesión, incluso si se redireccionan a un servidor web diferente, o en el caso de un reciclaje del proceso de trabajo.

1

La información a corto plazo, que solo necesita vivir hasta la próxima solicitud, también se puede almacenar en el ViewState. Esto significa que los objetos se serializan y se almacenan en la página enviada al navegador, que luego se publica en el servidor en un evento de clic o similar. Luego, el ViewState se decodifica y se convierte en objetos nuevamente, listo para ser recuperado.

1

Las sesiones no son malas, cumplen una función importante en la aplicación ASP.NET, y sirven datos que deben compartirse entre varias páginas durante la "sesión" de un usuario. Hay algunas sugerencias, diría usar la administración de la sesión SQL siempre que sea posible, y asegúrese de que los objetos que está utilizando en su colección de sesiones sean "serializables". Las mejores prácticas serían utilizar el objeto de sesión cuando sea absolutamente necesario compartir información de estado entre páginas y no usarlo cuando no sea necesario. La información no estará disponible en el lado del cliente. La clave de sesión se guarda en una cookie, en la cadena de consulta o en otros métodos, dependiendo de cómo esté configurada, y los objetos de la sesión están disponibles en la tabla de la base de datos (a menos que use InProc, en cuyo caso sus sesiones tendrán la posibilidad de desaparecer durante una recarga del sitio, o se volverán casi inútiles en la mayoría de los entornos en clúster).

1

Session as evil: No está en ASP.NET, configurado correctamente. Sí, es ideal ser tan apátrida como sea posible, pero la realidad es que no puedes llegar allí desde aquí. Sin embargo, puede hacer que la sesión se comporte de forma tal que disminuya su impacto: en particular, las sesiones de StateServer o de la base de datos.

+0

sus enlaces no funcionan ... – TheEmirOfGroofunkistan

+0

Sí, lamentablemente, ese sitio está caído. Buena llamada; Estoy matando los enlaces. –

5

Cuando desee almacenar información a la que se pueda acceder globalmente en su aplicación web, una forma de hacerlo es el atributo ThreadStatic. Esto convierte un miembro static de Class en un miembro compartido por el hilo actual, pero no por otros hilos. La ventaja de ThreadStatic es que no tiene que tener un contexto web disponible. Por ejemplo, si tiene un servidor que no hace referencia al System.Web, pero también desea compartir información allí, puede configurar el id del usuario al comienzo de cada solicitud en la propiedad ThreadStatic, y hacer referencia a este en su dependencia sin la necesidad de tener acceso al objeto Session.

Como es static pero solo para un solo hilo, nos aseguramos de que otros visitantes simultáneos no reciban nuestra sesión. Esto funciona, siempre y cuando se asegure de que la propiedad se restablezca para cada solicitud. Esto lo convierte en un compañero ideal para las cookies.

3

Creo que usar el objeto Session es correcto en este caso, pero debe recordar La sesión puede caducar si no hay actividad del navegador durante mucho tiempo (la propiedad HttpSessionState.Timeout determina en cuántos minutos el proveedor del estado de sesión termina la sesión), es mejor verificar el valor de existencia antes de la devolución:

public static Account GetCurrentAccount(HttpSessionState session) 
{ 
    if (Session[ACCOUNT]!=null) 
     return (Account)Session[ACCOUNT]; 
    else 
     throw new Exception("Can't get current account. Session expired."); 
} 
+1

No lanzaría necesariamente una excepción, podría continuar y cargar el objeto de sesión (es decir, cargarlo de forma lenta). –

+1

Una excepción en el código es solo para llamar la atención, por supuesto. Debe ser reemplazado en caso de necesidad. –

1

Creo que el "mal" proviene del uso excesivo de la sesión. Si solo pega algo y todo (como usar variables globales para todo) terminará teniendo un rendimiento pobre y solo un desastre.

6

Una de las razones de su siniestra reputación es que los desarrolladores apresurados la sobreutilizan con literales de cadena en el código UI (en lugar de una clase auxiliar como la suya) como claves de elemento, y terminan con una gran bolsa de estado promiscuo no comprobable. Algún tipo de envoltorio es un requisito básico para el uso de sesiones no malvadas.

19

Sus dos opciones para almacenar temporalmente datos de formulario son, en primer lugar, almacenar la información de cada formulario en variables de estado de sesión y, en segundo lugar, pasar la información del formulario junto con los parámetros de URL. El uso de Cookies como una tercera opción potencial simplemente no es viable por el simple motivo de que muchos de sus visitantes probablemente tengan las cookies desactivadas (sin embargo, esto no afecta las cookies de sesión).Además, estoy asumiendo por la naturaleza de su pregunta que no desea almacenar esta información en una tabla de base de datos hasta que esté completamente comprometida.

El uso de variable (s) de sesión es la solución clásica a este problema, pero adolece de algunos inconvenientes. Entre ellos se encuentran (1) grandes cantidades de datos que pueden agotar la RAM del servidor si está utilizando la administración de sesiones inproc, (2) compartir variables de sesión en varios servidores en una granja de servidores requiere consideraciones adicionales, y (3) una aplicación diseñada profesionalmente protegerse contra la caducidad de la sesión (no solo lanzar una variable de sesión y usarla - si la sesión ha expirado, el lanzamiento arrojará un error). Sin embargo, para la gran mayoría de las aplicaciones, las variables de sesión son, sin duda, el camino a seguir.

La alternativa es pasar la información de cada formulario a lo largo de la URL. El principal problema con este enfoque es que tendrá que ser extremadamente cuidadoso con la información "de paso". Por ejemplo, si está recopilando información en cuatro páginas, deberá recopilar información en la primera, pasarla en la URL a la segunda página donde debe almacenarla en viewstate de esa página. Luego, cuando llame a la tercera página, recopilará los datos del formulario de la segunda página más las variables del estado de visualización y codificará ambos en la URL, etc. Si tiene cinco o más páginas o si el visitante saltará por el sitio, usted Tendrás un verdadero lío en tus manos. Tenga en cuenta también que toda la información deberá A) ser serializada a una cadena segura para URL y B) codificada de tal manera que evite hacks simples basados ​​en URL (por ejemplo, si pone el precio en texto claro y lo pasa) a lo largo, alguien podría cambiar el precio). Tenga en cuenta que puede reducir algunos de estos problemas creando un tipo de "administrador de sesión" y haga que administre las cadenas de URL para usted, pero igual tendría que ser extremadamente sensible a la posibilidad de que un enlace determinado pueda arruinar toda la sesión si no se maneja adecuadamente

Al final, utilizo las variables de URL solo para pasar datos muy limitados de una página a la siguiente (por ejemplo, la ID de un elemento como codificada en un enlace a ese elemento).

Supongamos, entonces, que efectivamente gestionará los datos de un usuario utilizando la capacidad de sesiones incorporada. ¿Por qué alguien te diría que "la sesión es malvada"? Bueno, además de las consideraciones sobre la carga de la memoria, la granja de servidores y la expiración presentadas anteriormente, la crítica principal de las variables de Sesión es que son, de hecho, variables sin tipo.

Afortunadamente, el uso prudente de las variables de sesión puede evitar problemas de memoria (artículos grandes se debe mantener en la base de datos de todos modos) y si está ejecutando un sitio lo suficientemente grande como para necesitar un conjunto de servidores, hay un montón de mecanismos disponibles para compartir el estado incorporado en ASP.NET (sugerencia: no usará almacenamiento inproc).

Para evitar esencialmente el resto de los inconvenientes de la sesión, le recomiendo que implemente un objeto para contener sus datos de sesión, así como algunas capacidades simples de administración de objetos de sesión. A continuación, créelas en un descendiente de la clase Page y use esta clase de Página descendiente para todas sus páginas. A continuación, es una cuestión simple acceder a sus datos de sesión a través de la clase de página como un conjunto de valores fuertemente tipados. Tenga en cuenta que los campos de su Objeto le darán una forma de acceder a cada una de sus "variables de sesión" de una manera fuertemente tipada (por ejemplo, un campo por variable).

¡Avíseme si esta es una tarea sencilla para usted o si desea un código de muestra!

+1

¡Buena explicación! –

+1

Gracias ... Lo intento. –

1

Todo lo que coloque en el objeto de sesión permanece allí durante la sesión a menos que se limpie. La mala administración de la memoria almacenada usando inproc y stateserver lo forzará a escalar antes de lo necesario. Almacene solo una ID para la sesión/usuario en la sesión y cargue lo que se necesita en el objeto de caché bajo demanda utilizando una clase auxiliar. De esta forma, puede ajustar su duración de acuerdo con la frecuencia con que usamos esos datos. La próxima versión de asp.net puede tener un caché distribuido (rumor).

0

¿Qué es una sesión, en una aplicación web?

Una sesión es una instancia única del navegador. Un solo usuario puede tener varias sesiones visitando su aplicación, con varias instancias del navegador ejecutándose con una identificación de sesión diferente en su máquina.