Introducción
En un entorno sin estado como una aplicación web, comprender el concepto de estado de sesión no tiene ningún significado real. No obstante, la gestión eficaz del estado es una característica imprescindible para la mayoría de las aplicaciones web. Microsoft ASP.NET, así como muchos otros entornos de programación del lado del servidor, proporcionan una capa de abstracción que permite a las aplicaciones almacenar datos persistentes por usuario y por aplicación.
Es importante tener en cuenta que el estado de sesión de una aplicación web son los datos que la aplicación almacena en caché y recupera a través de diferentes solicitudes. Una sesión representa todas las solicitudes enviadas por el usuario mientras está conectado al sitio, y el estado de la sesión es la recopilación de datos persistentes generados y consumidos por el usuario durante la sesión. El estado de cada sesión es independiente entre sí y deja de existir cuando finaliza la sesión del usuario.
El estado de la sesión no tiene correspondencia con ninguna de las entidades lógicas que componen el protocolo y la especificación HTTP. Las sesiones son una capa de abstracción creada por entornos de desarrollo del lado del servidor, como ASP tradicional y ASP.NET. La forma en que ASP.NET muestra el estado de la sesión y cómo se implementa internamente el estado de la sesión depende de la infraestructura de la plataforma. Por lo tanto, ASP tradicional y ASP.NET implementan el estado de la sesión de maneras completamente diferentes, y se esperan más mejoras y mejoras en la próxima versión de ASP.NET.
Este artículo analiza cómo implementar el estado de la sesión en ASP.NET 1.1 y cómo optimizar la administración del estado de la sesión en aplicaciones web administradas.
Descripción general del estado de sesión de ASP.NET
El estado de la sesión no forma parte de la infraestructura HTTP. Es decir, debe haber un componente estructural que vincule el estado de la sesión con cada solicitud entrante. El entorno de ejecución (ASP tradicional o ASP.NET) puede aceptar palabras clave como Sesión y utilizarlas para indicar el bloque de datos almacenado en el servidor. Para resolver correctamente las llamadas a un objeto de sesión, el entorno de ejecución debe agregar el estado de la sesión al contexto de llamada de la solicitud que se está procesando. La forma en que se hace esto varía según la plataforma, pero es fundamental para las aplicaciones web con estado.
En ASP tradicional, el estado de la sesión se implementa como objetos COM de subproceso libre contenidos en la biblioteca asp.dll. (¿Tiene curiosidad? El CLSID de este objeto es en realidad D97A6DA0-A865-11cf-83AF-00A0C90C2BD8). Este objeto almacena datos organizados como una colección de pares de nombre/valor. El marcador de posición "nombre" representa la clave utilizada para recuperar la información, mientras que el marcador de posición "valor" representa lo que se almacena en el estado de la sesión. Los pares de nombre/valor se agrupan por ID de sesión para que cada usuario vea solo los pares de nombre/valor que creó.
En ASP.NET, la interfaz de programación para el estado de la sesión es casi la misma que en ASP tradicional. Pero sus implementaciones básicas son completamente diferentes. El primero es más flexible, escalable y tiene capacidades de programación más sólidas que el segundo. Antes de profundizar en el estado de la sesión ASP.NET, revisemos brevemente algunas de las capacidades estructurales de la infraestructura de la sesión ASP.NET.
En ASP.NET, cualquier solicitud HTTP entrante se canaliza a través del módulo HTTP. Cada módulo puede filtrar y modificar la gran cantidad de información que lleva la solicitud. La información asociada con cada solicitud se denomina "contexto de llamada", que está representado por el objeto HttpContext en programación. No debemos pensar en el contexto de solicitud como otro contenedor de información de estado, aunque la colección de Elementos que proporciona es solo un contenedor de datos. El objeto HttpContext se diferencia de todos los demás objetos de estado (por ejemplo, Sesión, Aplicación y Caché) en que tiene una vida útil limitada más allá del tiempo necesario para manejar la solicitud. Cuando una solicitud pasa por una serie de módulos HTTP registrados, su objeto HttpContext contendrá una referencia al objeto de estado. Cuando la solicitud finalmente se puede procesar, el contexto de llamada asociado se vincula a la sesión específica (Sesión) y a los objetos de estado global (Aplicación y Caché).
El módulo HTTP responsable de configurar el estado de la sesión de cada usuario es SessionStateModule. La estructura de este módulo está diseñada en base a la interfaz IHttpModule, que proporciona una gran cantidad de servicios relacionados con el estado de la sesión para aplicaciones ASP.NET. Incluye la generación de ID de sesión, la gestión de sesiones sin cookies, la recuperación de datos de sesión de proveedores de estado externos y la vinculación de datos al contexto de llamada de la solicitud.
El módulo HTTP no almacena datos de sesión internamente. El estado de la sesión siempre se guarda en un componente externo llamado "proveedor de estado". El proveedor de estado encapsula completamente los datos del estado de la sesión y se comunica con otras partes a través de los métodos de la interfaz ISateClientManager. El módulo HTTP de estado de sesión llama a métodos en esta interfaz para leer y guardar el estado de la sesión. ASP.NET 1.1 admite tres proveedores de estado diferentes, como se muestra en la Tabla 1.
Tabla 1: Estado Cliente Proveedor
Proveedor Descripción
Los valores de sesión de InProc siguen siendo objetos activos en la memoria del proceso de trabajo ASP.NET (aspnet_wp.exe o w3wp.exe en Microsoft® Windows Server® 2003). Esta es la opción predeterminada.
Los valores de la sesión de StateServer se serializan y almacenan en la memoria en un proceso separado (aspnet_state.exe). El proceso también puede ejecutarse en otras computadoras.
Los valores de la sesión de SQLServer se serializan y almacenan en tablas de Microsoft® SQL Server®. Las instancias de SQL Server se pueden ejecutar de forma local o remota.
El módulo HTTP de estado de sesión lee el proveedor de estado seleccionado actualmente de la sección <sessionState> del archivo web.config.
<sessionState mode="InProc | StateServer | SQLServer />;
Dependiendo del valor del atributo de modo, el estado de la sesión se recuperará y almacenará en diferentes procesos a través de diferentes pasos. De forma predeterminada, el estado de la sesión se almacena en el local El proceso de trabajo de ASP.NET en casos especiales se almacena en una ranura dedicada del objeto de caché de ASP.NET (no se puede acceder mediante programación). El estado de la sesión también se puede almacenar externamente, incluso en un proceso remoto (por ejemplo, en Windows). Servicio NT llamado aspnet_state.exe). La tercera opción es almacenar el estado de la sesión en una tabla de base de datos dedicada administrada por SQL Server 2000.
El módulo HTTP deserializa el valor de la sesión al comienzo de la solicitud, convirtiéndolos en objetos de diccionario. (En realidad, se accede a objetos de tipo HttpSessionState) mediante programación a través de la propiedad Session expuesta por las clases (por ejemplo, HttpContext y Page. El enlace dura hasta que finaliza la solicitud. Si la solicitud se completa con éxito, todos los valores de estado se vuelven a serializar). al proveedor de estado y disponible para otras solicitudes.
La Figura 1 ilustra la comunicación entre la página ASP.NET solicitada y los valores de la sesión. El código utilizado por cada página está relacionado con el atributo de sesión en la clase de página. igual que el del ASP tradicional.
Figura 1: Arquitectura del estado de la sesión en ASP.NET 1.1
El valor físico del estado de la sesión está bloqueado durante el tiempo necesario para completar la solicitud. Este bloqueo lo gestiona internamente el módulo HTTP y se utiliza para sincronizar el acceso al estado de la sesión.
El módulo de estado de sesión crea una instancia del proveedor de estado de la aplicación y lo inicializa con información leída del archivo web.config. A continuación, cada proveedor continuará con sus propias operaciones de inicialización. Dependiendo del tipo de proveedor, sus operaciones de inicialización variarán mucho. Por ejemplo, el administrador de estado de SQL Server abrirá una conexión a una base de datos determinada, mientras que el administrador fuera de proceso verificará el puerto TCP especificado. Por otro lado, el administrador de estado de InProc almacenará una referencia a la función de devolución de llamada. Esta acción se realiza cuando un elemento se elimina del caché y se utiliza para activar el evento Session_OnEnd de la aplicación.
Acceso sincrónico al estado de la sesión
¿Qué sucede cuando una página web realiza una llamada muy simple e intuitiva a la propiedad Sesión? Muchas operaciones se realizan en segundo plano, como se muestra en el siguiente código engorroso:
int siteCount = Convert.ToInt32(Session["Counter"]);
El código anterior en realidad accede al valor de sesión creado por el módulo HTTP en la memoria local. lee datos de un proveedor estatal específico (ver Figura 1). ¿Qué sucede si otras páginas también intentan acceder al estado de la sesión de forma sincrónica? En este caso, la solicitud actual puede dejar de procesar datos inconsistentes o obsoletos. Para evitar esto, el módulo de estado de sesión implementará un mecanismo de bloqueo de lector/escritor y acceso a la cola a los valores de estado. Las páginas con permisos de escritura en el estado de sesión conservarán el bloqueo de escritura para esa sesión hasta que finalice la solicitud.
Una página puede solicitar permiso de escritura para el estado de la sesión estableciendo la propiedad EnableSessionState de la directiva @Page en verdadero. (Esta es la configuración predeterminada). Sin embargo, una página también puede tener acceso de solo lectura al estado de la sesión, por ejemplo, cuando la propiedad EnableSessionState está establecida en ReadOnly. En este caso, el módulo retendrá el bloqueo del lector para esa sesión hasta que finalice la solicitud de esa página. Como resultado, se producirán lecturas simultáneas.
Si una solicitud de página establece un bloqueo de lector, otras solicitudes simultáneas en la misma sesión no podrán actualizar el estado de la sesión, pero al menos podrán leer. Es decir, si actualmente se está procesando una solicitud de solo lectura para una sesión, la solicitud de solo lectura pendiente tendrá mayor prioridad que una solicitud que requiera acceso completo. Si una solicitud de página establece un bloqueo de escritura para el estado de la sesión, todas las demás páginas se bloquearán independientemente de si desean leer o escribir contenido. Por ejemplo, si dos fotogramas intentan escribir en la sesión al mismo tiempo, un fotograma debe esperar hasta que el otro haya terminado antes de poder escribir.
Comparación de proveedores de estado
De forma predeterminada, las aplicaciones ASP.NET almacenan el estado de la sesión en la memoria de un proceso de trabajo, específicamente en una ranura dedicada del objeto Cache. Cuando se selecciona el modo InProc, el estado de la sesión se almacena en ranuras dentro del objeto Cache. Esta ranura está marcada como privada y no se puede acceder a ella mediante programación. En otras palabras, si enumera todos los elementos en la caché de datos de ASP.NET, no se devolverá ningún objeto similar al estado de sesión dado. Los objetos de caché proporcionan dos tipos de espacios: espacios privados y espacios públicos. Los programadores pueden agregar y manejar espacios públicos, pero los espacios privados solo pueden ser utilizados por el sistema (específicamente, las clases definidas en el elemento system.web).
El estado de cada sesión activa ocupa un espacio dedicado en la memoria caché. El nombre de la ranura se basa en el ID de la sesión y su valor es una instancia de una clase interna no declarada denominada SessionStateItem. El proveedor de estado de InProc obtiene el ID de la sesión y recupera el elemento correspondiente en la memoria caché. Luego, el contenido del objeto SessionStateItem se ingresa en el objeto del diccionario HttpSessionState y la aplicación accede a él a través de la propiedad Session. Tenga en cuenta que hay un error en ASP.NET 1.0 que hace que las ranuras privadas del objeto Cache se puedan enumerar mediante programación. Si ejecuta el siguiente código en ASP.NET 1.0, podrá enumerar los elementos correspondientes a los objetos contenidos en cada estado de sesión actualmente activo.
foreach (elemento de entrada del diccionario en caché)
{
Response.Write(elem.Key + ": " + elem.Value.ToString());
}
Este error se resolvió en ASP.NET 1.1 y cuando enumera el contenido almacenado en caché, ya no se mostrarán ranuras del sistema.
InProc es probablemente, con diferencia, la opción de acceso más rápida. Pero tenga en cuenta que cuantos más datos se almacenen en una sesión, más memoria consumirá el servidor web, lo que podría aumentar el riesgo de degradación del rendimiento. Si planea utilizar alguna solución fuera de proceso, debe considerar cuidadosamente los posibles efectos de la serialización y deserialización. La solución fuera de proceso utiliza un servicio de Windows NT (aspnet_state.exe) o una tabla de SQL Server para almacenar los valores de la sesión. Por lo tanto, el estado de la sesión permanece fuera del proceso de trabajo de ASP.NET y se requieren capas adicionales de código para serializar y deserializar entre el estado de la sesión y el medio de almacenamiento real. Esto sucede cada vez que se procesa una solicitud y luego debe optimizarse al máximo.
Debido a que los datos de la sesión deben copiarse del repositorio externo al diccionario de la sesión local, la solicitud genera una degradación del rendimiento que oscila entre el 15 % (fuera de proceso) y el 25 % (SQL Server). Tenga en cuenta que, si bien esto es sólo una estimación aproximada, debería estar cerca del impacto mínimo y el impacto máximo será mucho mayor que esto. De hecho, esta estimación no tiene en cuenta plenamente la complejidad de los tipos realmente guardados en el estado de sesión.
En el escenario de almacenamiento fuera de proceso, el estado de la sesión sobrevive más tiempo, lo que hace que la aplicación sea más poderosa porque protege contra fallas de Microsoft® Internet Information Services (IIS) y ASP.NET. Al separar el estado de la sesión de las aplicaciones, también puede ampliar más fácilmente las aplicaciones existentes a las arquitecturas Web Farm y Web Garden. Además, el estado de la sesión se almacena en un proceso externo, lo que esencialmente elimina el riesgo de pérdida periódica de datos debido a bucles de proceso.
A continuación se explica cómo utilizar los servicios de Windows NT. Como se mencionó anteriormente, el servicio NT es un proceso llamado aspnet_state.exe, generalmente ubicado en la carpeta C:WINNTMicrosoft.NETFrameworkv1.1.4322.
El directorio real depende de la versión de Microsoft® .NET Framework que esté ejecutando actualmente. Antes de utilizar el servidor de estado, debe asegurarse de que el servicio esté listo y ejecutándose en la computadora local o remota que se utiliza como dispositivo de almacenamiento de sesión. El servicio estatal forma parte de ASP.NET y se instala con él, por lo que no es necesario ejecutar un instalador adicional. De forma predeterminada, el servicio de estado no se está ejecutando y debe iniciarse manualmente. La aplicación ASP.NET intentará establecer una conexión con el servidor de estado inmediatamente después de cargarse. Por lo tanto, el servicio debe estar listo y ejecutándose; de lo contrario, se generará una excepción HTTP. La siguiente imagen muestra el cuadro de diálogo de propiedades del servicio.
Figura 2: Cuadro de diálogo Propiedades del servidor de estado ASP.NET
Las aplicaciones ASP.NET necesitan especificar la dirección TCP/IP de la computadora donde se encuentra el servicio de estado de sesión. Se deben ingresar las siguientes configuraciones en el archivo web.config de la aplicación.
<configuración>;
<sistema.web>;
<estadodesesión
modo="Servidor de Estado"
stateConnectionString="tcpip=expoware:42424" />;
</system.web>;
</configuration>;
El atributo stateConnectionString contiene la dirección IP de la computadora y el puerto utilizado para el intercambio de datos. La dirección predeterminada de la computadora es 127.0.0.1 (localhost) y el puerto predeterminado es 42424. También puede indicar la computadora por su nombre. El uso de una computadora local o remota es completamente transparente para el código. Tenga en cuenta que no se pueden utilizar caracteres que no sean ASCII en el nombre y que el número de puerto es obligatorio.
Si utiliza almacenamiento de sesión fuera de proceso, el estado de la sesión seguirá existiendo y estará disponible para uso futuro independientemente de lo que suceda con el proceso de trabajo de ASP.NET. Si se interrumpe el servicio, los datos se conservarán y se recuperarán automáticamente cuando se restablezca el servicio. Sin embargo, si el servicio del proveedor de estado se detiene o falla, se perderán datos. Si desea que su aplicación sea potente, utilice el modo SQLServer en lugar del modo StateServer.
<configuración>;
<sistema.web>;
<estadodesesión
modo="Servidor SQL"
sqlConnectionString="servidor=127.0.0.1;uid=<id de usuario>;;pwd=<contraseña>;;" />;
</system.web>;
</configuration>;
Puede especificar la cadena de conexión a través del atributo sqlConnectionString. Tenga en cuenta que la cadena de atributo debe contener el ID de usuario, la contraseña y el nombre del servidor. No puede contener etiquetas como Base de datos y Catálogo inicial porque esta información tiene por defecto un nombre fijo. Los ID de usuario y las contraseñas se pueden reemplazar con configuraciones de seguridad integradas.
¿Cómo crear una base de datos? ASP.NET proporciona dos pares de scripts para configurar el entorno de la base de datos. El primer par de scripts se denominan InstallSqlState.sql y UninstallSqlState.sql y se encuentran en la misma carpeta que el servicio Session State NT. Crean una base de datos llamada ASSPState y varios procedimientos almacenados. Sin embargo, los datos se almacenan en la base de datos TempDB del área de almacenamiento temporal de SQL Server. Esto significa que si se reinicia la computadora con SQL Server, los datos de la sesión se perderán.
Para solucionar esta limitación, utilice un segundo par de secuencias de comandos. El segundo par de scripts se denominan InstallPersistSqlState.sql y UninstallPersistSqlState.sql. En este caso se crea la base de datos ASPState, pero las tablas se crean en la misma base de datos y también son persistentes. Cuando instala el soporte de SQL Server para sesiones, también se crea un trabajo para eliminar sesiones caducadas en la base de datos del estado de la sesión. El trabajo se denomina ASPState_Job_DeleteExpiredSessions y siempre está ejecutándose. Tenga en cuenta que para que este trabajo funcione correctamente, el servicio SQLServerAgent debe estar ejecutándose.
No importa qué modo elija, la forma en que se codifican las operaciones de estado de sesión no cambia. Siempre puedes trabajar en la propiedad Session y leer y escribir valores normalmente. Todas las diferencias de comportamiento se manejan en un nivel inferior de abstracción. La serialización del estado es quizás la diferencia más importante entre los modos de sesión.
Serialización y deserialización de estado
Cuando se utiliza el modo en proceso, los objetos se almacenan en estado de sesión como instancias activas de sus respectivas clases. Si no se produce una serialización y deserialización real, significa que realmente puede almacenar cualquier objeto que cree en la sesión (incluidos los objetos que no se pueden serializar y los objetos COM), y acceder a ellos no será demasiado costoso. Si elige un proveedor estatal fuera de proceso, es otra historia.
En una arquitectura fuera de proceso, los valores de la sesión se copian desde el medio de almacenamiento local (base de datos externa del AppDomain) a la memoria del AppDomain que maneja la solicitud. Se requiere una capa de serialización/deserialización para realizar esta tarea y representa uno de los principales costos de los proveedores de estado fuera de proceso. El principal impacto que esta situación tiene en su código es que solo se pueden almacenar objetos serializables en el diccionario de sesión.
ASP.NET utiliza dos métodos para serializar y deserializar datos, según el tipo de datos involucrados. Para los tipos básicos, ASP.NET utiliza un serializador interno optimizado; para otros tipos, incluidos objetos y clases definidas por el usuario, ASP.NET utiliza el formateador binario .NET. Los tipos básicos incluyen cadenas, fechas y horas, valores booleanos, bytes, caracteres y todos los tipos numéricos. Para estos tipos, usar un serializador hecho a medida es más rápido que usar el formateador binario .NET común predeterminado.
El serializador optimizado no se publica ni se documenta. Es simplemente un lector/escritor binario y utiliza una arquitectura de almacenamiento simple pero efectiva. El serializador usa la clase BinaryWriter para escribir una representación en bytes del tipo y luego escribe una representación en bytes del valor correspondiente a ese tipo. Al leer bytes serializados, la clase primero extrae un byte, detecta el tipo de datos que se va a leer y luego llama al método ReadXxx específico del tipo en la clase BinaryReader.
Tenga en cuenta que el tamaño de los tipos booleanos y numéricos es bien conocido, pero no el de las cadenas. En el flujo de datos subyacente, la cadena siempre tiene como prefijo una longitud fija (un código entero de 7 bits escrito a la vez), y el lector utiliza este hecho para determinar el tamaño correcto de la cadena. El valor de la fecha se guarda escribiendo solo el número total de tokens que componen la fecha. Por tanto, para serializar la sesión, la fecha debe ser de tipo Int64.
Puede utilizar la clase BinaryFormatter para realizar operaciones de serialización en objetos más complejos (así como en objetos personalizados) siempre que la clase que la contiene esté marcada como serializable. Todos los tipos no básicos se identifican con el mismo ID de tipo y se almacenan en el mismo flujo de datos que los tipos básicos. En general, las operaciones de serialización pueden provocar una degradación del rendimiento del 15 % al 25 %. Sin embargo, tenga en cuenta que se trata de una estimación aproximada basada en el supuesto de que se utilizan tipos básicos. Cuanto más complejos sean los tipos utilizados, mayor será la sobrecarga.
Es difícil implementar un almacenamiento eficiente de datos de sesión sin un uso extensivo de tipos primitivos. Entonces, al menos en teoría, usar tres espacios de sesión para guardar tres propiedades de cadena diferentes de un objeto es mejor que serializar todo el objeto. Pero ¿qué pasa si el objeto que deseas serializar contiene 100 propiedades? ¿Quieres utilizar 100 espacios o solo uno? En muchos casos, un mejor enfoque es convertir un tipo complejo en varios tipos más simples. Este enfoque se basa en convertidores de tipos. Un "convertidor de tipos" es un serializador ligero que devuelve las propiedades clave de un tipo como una colección de cadenas. Los convertidores de tipos son clases externas que están vinculadas a una clase base mediante atributos. Depende del escritor decidir qué propiedades se guardan y cómo. Los convertidores de tipos también son útiles para el almacenamiento ViewState y representan un método más eficiente de almacenamiento de sesiones que los formateadores binarios.
Ciclo de vida de la sesión
Un punto importante sobre la gestión de sesiones de ASP.NET es que el ciclo de vida del objeto de estado de sesión comienza sólo cuando se agrega el primer elemento al diccionario en memoria. Una sesión de ASP.NET se considera iniciada solo después de ejecutar el siguiente fragmento de código.
Session["MySlot"] = "Algunos datos";
El diccionario de sesión generalmente contiene el tipo de objeto. Para leer datos al revés, el valor devuelto debe convertirse a un tipo más específico.
string data = (string) Session["MySlot"];
cuando la página guarda datos en la sesión, el valor se cargará en la clase de diccionario especialmente diseñada contenida en la clase HttpSessionState. El contenido del diccionario se carga en el proveedor de estado cuando se completa la solicitud actualmente procesada. Si el estado de la sesión está vacío porque los datos no se colocaron en el diccionario mediante programación, los datos no se serializarán en el medio de almacenamiento y, lo que es más importante, no se entregarán en ASP.NET Cache, SQL Server o NT State Services Create. una ranura para realizar un seguimiento de la sesión actual. Esto se debe a razones de rendimiento, pero tiene un impacto importante en cómo se manejan los ID de sesión: se generará un nuevo ID de sesión para cada solicitud hasta que se almacenen algunos datos en el diccionario de la sesión.
Cuando es necesario conectar el estado de la sesión con una solicitud en proceso, el módulo HTTP recupera el ID de la sesión (si no es la solicitud que inicia) y lo busca en el proveedor de estado configurado. Si no se devuelven datos, el módulo HTTP genera una nueva ID de sesión para la solicitud. Esto se puede probar fácilmente con la siguiente página:
<%@ Page Language="C#" Trace="true" %>;
</html>;
<cuerpo>;
<formulario runat="servidor">;
<asp:botón runat="servidor" text="Hacer clic" />;
</formulario>;
</cuerpo>;
</html>;
Cada vez que haga clic en el botón y regrese a la página, se generará una nueva ID de sesión y se registrará la información de seguimiento.
Figura 3: En una aplicación que no almacena datos en un diccionario de sesión, se genera una nueva ID de sesión para cada solicitud.
¿Qué pasa con el evento Session_OnStart? ¿Se generará el evento también para cada solicitud? Si su aplicación define un controlador Session_OnStart, el estado de la sesión siempre se guarda, incluso si el estado de la sesión está vacío. Por lo tanto, el ID de sesión siempre es constante para todas las solicitudes después de la primera solicitud. Utilice el controlador Session_OnStart solo cuando sea absolutamente necesario.
Si una sesión caduca o se abandona, su ID de sesión no cambia la próxima vez que se accede a la aplicación sin estado. Está diseñado para que el ID de la sesión persista hasta el final de la sesión del navegador, incluso si el estado de la sesión expira. Es decir, siempre se utiliza el mismo ID de sesión para representar varias sesiones siempre que la instancia del navegador sea la misma.
El evento Session_OnEnd marca el final de una sesión y se utiliza para ejecutar cualquier código de limpieza necesario para finalizar la sesión. Sin embargo, tenga en cuenta que este evento solo se admite en el modo InProc, es decir, solo cuando los datos de la sesión se almacenan en un proceso de trabajo ASP.NET. Para que se genere el evento Session_OnEnd, primero debe existir un estado de sesión, lo que significa que algunos datos deben almacenarse en el estado de sesión y se debe completar al menos una solicitud.
En el modo InProc, el estado de la sesión agregado a la caché como elementos recibe una política de tiempo de vencimiento variable. La caducidad variable significa que si un artículo no se utiliza dentro de un cierto período de tiempo, se eliminará. Se restablecerá el tiempo de vencimiento de cualquier solicitud procesada durante este período. El intervalo del elemento de estado de la sesión se establece en el tiempo de espera de la sesión. La técnica utilizada para restablecer el tiempo de vencimiento del estado de la sesión es muy simple e intuitiva: el módulo HTTP de la sesión simplemente lee los elementos del estado de la sesión almacenados en la caché de ASP.NET. Si se conoce la estructura interna del objeto de caché de ASP.NET, el módulo realizará cálculos para restablecer el tiempo de vencimiento de la variable. Entonces, cuando el elemento almacenado en caché caduca, la sesión expira.
Los elementos caducados se eliminarán automáticamente del caché. El módulo de sesión de estado también representa una función de eliminación de devolución de llamada como parte de la política de tiempo de vencimiento para este proyecto. El caché llamará automáticamente a la función de eliminación, que luego generará el evento Session_OnEnd. Si una aplicación realiza la gestión de sesiones a través de un componente fuera de proceso, el evento de finalización nunca se generará.
Sesiones sin cookies
Cada sesión activa de ASP.NET se identifica mediante una cadena de 120 bits que consta únicamente de los caracteres permitidos por la URL. El ID de sesión se genera utilizando un proveedor criptográfico generador de números aleatorios (RNG). El proveedor de servicios devuelve una secuencia de 15 números generados aleatoriamente (15 bytes x 8 bits = 120 bits). Luego, la matriz de números aleatorios se asigna a caracteres de URL válidos y se devuelve como una cadena.
La cadena de ID de sesión se envía al navegador y se devuelve a la aplicación del servidor de dos maneras: usando una cookie (como en ASP tradicional) o una URL modificada. De forma predeterminada, el módulo de estado de la sesión creará una cookie HTTP en el lado del cliente, pero se puede usar una URL modificada que incruste la cadena de ID de la sesión (especialmente para navegadores que no admiten cookies). El método que se utilice depende de los ajustes de configuración almacenados en el archivo web.config de la aplicación. Para configurar los ajustes de la sesión, puede utilizar la sección <sessionState> y el atributo Sin cookies.
<sessionState cookieless="true|false" />;
de forma predeterminada, el atributo sin cookies es falso, lo que indica que se utilizan cookies. De hecho, una cookie es simplemente un archivo de texto colocado en el disco duro del cliente por una página web. En ASP.NET, una cookie está representada por una instancia de la clase HttpCookie. Normalmente, una cookie contiene un nombre, un conjunto de valores y una hora de caducidad. Cuando el atributo Cookieless se establece en falso, el módulo de estado de la sesión creará una cookie llamada ASP.NET_SessionId y almacenará el ID de la sesión en ella. El siguiente pseudocódigo muestra el proceso de creación de una cookie:
HttpCookie sessionCookie;
sessionCookie = new HttpCookie("ASP.NET_SessionId", sessionID);
sessionCookie.Path = "/";
El tiempo de vencimiento de la cookie de sesión es muy corto y el tiempo de vencimiento se actualiza después de que cada solicitud se realiza correctamente. El atributo Expires de la cookie indica el tiempo de vencimiento de la cookie en el cliente. Si la cookie de sesión no se establece explícitamente, la propiedad Expires tiene como valor predeterminado DateTime.MinValue, que es la unidad de tiempo más pequeña permitida por .NET Framework.
Para deshabilitar las cookies de sesión, establezca el atributo Sin cookies en verdadero en el archivo de configuración de la siguiente manera:
<configuración>;
<sistema.web>;
<sessionState Cookieless="true" />;
</system.web>;
</configuration>;
En este punto, suponga que solicita la página en la siguiente URL:
http://www.contoso.com/sample.aspxEl
contenido real que se muestra en la barra de direcciones del navegador será diferente y ahora contendrá el ID de la sesión. , como se muestra a continuación:
http://www.contoso.com/(5ylg0455mrvws1uz5mmaau45)/sample.aspx
Al crear una instancia del módulo HTTP de estado de sesión, el módulo comprueba el valor del atributo sin cookies. Si es verdadero, redirige la solicitud (HTTP 302) a una URL virtual modificada que contiene el ID de sesión inmediatamente anterior al nombre de la página. Cuando la solicitud se procese nuevamente, el ID de la sesión se incluirá en la solicitud. Si se realiza una solicitud para iniciar una nueva sesión, el módulo HTTP genera una nueva ID de sesión y luego redirige la solicitud. Si la solicitud se devuelve, el ID de sesión ya existe porque las devoluciones de datos utilizan URL relativas.
La desventaja de utilizar sesiones sin cookies es que el estado de la sesión se pierde si se llama a una URL absoluta. Al utilizar cookies, puede borrar la barra de direcciones, ir a otra aplicación y luego volver a la aplicación anterior y recuperar el mismo valor de sesión. Si hace esto mientras las cookies de sesión están deshabilitadas, los datos de la sesión se perderán. Por ejemplo, el siguiente código interrumpirá la sesión:
<a runat="server" href="/code/page.aspx">;Click</a>;
Si necesita utilizar una URL absoluta, utilice algunos trucos para cambie manualmente el ID de sesión agregado a la URL. Puede llamar al método ApplyAppPathModifier en la clase HttpResponse.
<a runat="servidor"
href=<% =Response.ApplyAppPathModifier("/code/page.aspx")%>; >;Click</a>;
El método ApplyAppPathModifier utilizará una cadena que representa la URL y devolverá la URL absoluta que incorpora la información de la sesión. Esta técnica es particularmente útil cuando, por ejemplo, necesita redirigir desde una página HTTP a una página HTTPS.
El estado de sesiónresumida
se introdujo originalmente con ASP tradicional como una API basada en diccionario que permitía a los desarrolladores almacenar datos personalizados durante una sesión. En ASP.NET, el estado de la sesión admite dos características principales: almacenamiento y transferencia de ID de sesión sin cookies y proveedores de estado donde se almacenan realmente los datos de la sesión. Para implementar estas dos nuevas capacidades, ASP.NET aprovecha el módulo HTTP para controlar el enlace entre el estado de la sesión y el contexto de la solicitud que se procesa.
En ASP tradicional, usar el estado de sesión significa usar cookies. Este ya no es el caso en ASP.NET, ya que se puede utilizar una arquitectura sin cookies. Con el poder del módulo HTTP, la URL solicitada se puede descomponer para que contenga el ID de la sesión y luego redirigir. A continuación, el módulo HTTP extrae el ID de sesión de la URL y lo utiliza para recuperar cualquier estado almacenado.
El estado físico de una sesión se puede almacenar en tres ubicaciones: memoria en proceso, memoria fuera de proceso y tablas de SQL Server. Los datos deben serializarse/deserializarse antes de que la aplicación pueda utilizarlos. El módulo HTTP copia el valor de la sesión del proveedor en la memoria de la aplicación al comienzo de la solicitud. Una vez completada la solicitud, el estado modificado se devuelve al proveedor. Esta comunicación de datos tendrá diversos grados de efectos adversos en el rendimiento, pero mejorará en gran medida la confiabilidad y la estabilidad y facilitará el apoyo a las arquitecturas web de la granja y el jardín web.