asp.net - net - sessionstate mode
Sesión ASP.Net (14)
Deseo 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?
He estado usando objetos de sesión y usando 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;
}
Muchas fuentes me han dicho que "la sesión es malvada", así que esa 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é.
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.
Creo que usar el objeto Session es correcto en este caso, pero debes recordar que Session 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 la sesión finaliza la sesión), así que es mejor verificar el valor de la 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.");
}
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 una 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 back-end que no hace referencia a System.Web
, pero también desea compartir información allí, puede establecer la id
del usuario al comienzo de cada solicitud en la propiedad ThreadStatic
y hacer referencia a ella en su dependencia sin la necesidad de tener acceso al objeto Session
.
Debido a que es static
pero solo a un único 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.
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 constantemente nos referimos a él por su nombre, dirección de correo electrónico, autorización, etc.
Otros pequeños trozos de información que no necesitan persistencia a largo plazo, usamos una combinación de cookies y viewstate.
Hasta donde yo sé, la 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.
La información a corto plazo, que solo necesita vivir hasta la próxima solicitud, también se puede almacenar en 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.
Las sesiones no son malvadas, 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).
No hay nada intrínsecamente malo con el estado de la sesión.
Hay un par de cosas a tener en cuenta que pueden morderte:
- Si el usuario presiona el botón Atrás del navegador, volverá a la página anterior, pero el estado de la sesión no se revertirá. Entonces su cuenta actual podría no ser lo que originalmente era en la página.
- Los procesos ASP.NET pueden ser reciclados por IIS. Cuando eso suceda, la siguiente solicitud comenzará un nuevo proceso. Si está usando el estado de la sesión de proceso, el valor predeterminado, se habrá ido :-(
- 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 lo hará.
- El uso del estado de sesión fuera de proceso requiere que todos los objetos almacenados en el estado de la sesión sean serializables.
- Si el usuario abre una segunda ventana del navegador, esperará tener una segunda y distinta aplicación, pero es muy probable que el estado de la sesión se comparta entre dos. Entonces, cambiar la cuenta actual en una ventana del navegador hará lo mismo en la otra.
Sesión como malvado: no 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.
Sus dos opciones para almacenar temporalmente los datos del formulario son, en primer lugar, almacenar la información de cada formulario en la (s) variable (s) de estado de la sesión y, en segundo lugar, pasar la información del formulario junto con los parámetros de la 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 variables de URL solo para pasar datos muy limitados de una página a la siguiente (por ejemplo, la identificación de un artículo codificada en un enlace a ese artículo).
Supongamos, entonces, que efectivamente administraría los datos de un usuario utilizando la capacidad de Sesiones integrada. ¿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 (los elementos grandes deben mantenerse en la base de datos de todos modos) y si está ejecutando un sitio lo suficientemente grande como para necesitar una granja de servidores, hay muchos mecanismos disponibles para compartir el estado integrado en ASP .NET (sugerencia: no utilizará el 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!
Todo lo que coloque en el objeto de sesión permanecerá allí durante la sesión a menos que esté limpio. 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).
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.
http://www.tigraine.at/2008/07/17/session-handling-in-aspnet/
espero que esto ayude.
¿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.