Pregunta

Estoy deseando almacenar el estado " " " de algunas acciones que el usuario está realizando en una serie de diferentes formularios web de ASP.Net. ¿Cuáles son mis opciones para el estado de persistencia y cuáles son las ventajas y desventajas de cada solución?

He estado usando objetos de sesión y usando algunos métodos de ayuda para escribir los objetos con fuerza:

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

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

Numerosas fuentes me han dicho que " Session is evil " ;, así que esa es realmente la causa raíz de esta pregunta. Quiero saber lo que piensa "mejor práctica" y por qué.

¿Fue útil?

Solución

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

Hay un par de cosas que debes tener en cuenta que podrían morderte:

  1. Si el usuario presiona el botón de retroceso del navegador, volverá a la página anterior pero su estado de sesión no se revertirá. Por lo tanto, es posible que su CurrentAccount no sea lo que estaba originalmente en la página.
  2. Los procesos ASP.NET pueden ser reciclados por IIS. Cuando eso suceda, la próxima solicitud comenzará un nuevo proceso. Si está utilizando el estado de sesión de proceso, el valor predeterminado, desaparecerá :-(
  3. La sesión también puede agotar el tiempo de espera con el mismo resultado si el usuario no está activo durante algún tiempo. El valor predeterminado es 20 minutos, así que un buen almuerzo lo hará.
  4. El uso del estado de sesión fuera de proceso requiere que todos los objetos almacenados en el estado de sesión sean serializables.
  5. Si el usuario abre una segunda ventana del navegador, esperará tener una segunda aplicación distinta, pero lo más probable es que el estado de la sesión se comparta entre dos. Por lo tanto, cambiar la CurrentAccount en una ventana del navegador hará lo mismo en la otra.

Otros consejos

Sus dos opciones para almacenar temporalmente los datos del formulario son, primero, almacenar la información de cada formulario en la (s) variable (s) de estado de la sesión y, segundo, pasar la información del formulario utilizando 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 desactivadas las cookies (esto no afecta a las cookies de sesión, sin embargo). Además, por la naturaleza de su pregunta, supongo que no desea almacenar esta información en una tabla de base de datos hasta que esté completamente confirmada.

El uso de variables de sesión es la solución clásica a este problema, pero tiene algunos inconvenientes. Entre ellos se encuentran (1) grandes cantidades de datos que pueden usar la memoria RAM del servidor si está usando la administración de sesión en proceso, (2) compartir variables de sesión en múltiples servidores en una granja de servidores requiere consideraciones adicionales, y (3) una aplicación diseñada profesionalmente debe evite el vencimiento de la sesión (no solo eche una variable de sesión y úsela; 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 al pasar '' información. Por ejemplo, si está recopilando información en cuatro páginas, tendría que recopilar información en la primera, pásela en la URL a la segunda página donde debe almacenarla en el estado de visualización 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á ambas en la URL, etc. Si tiene cinco o más páginas o si el visitante saltará por el sitio, Tendré 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 se eviten hacks simples basados ??en URL (por ejemplo, si pone el precio en texto sin cifrar 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 pídale que administre las cadenas de URL para usted, pero aún así tendría que ser extremadamente sensible a la posibilidad de que cualquier enlace dado pueda destruir la sesión completa de alguien si no se administra correctamente.

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

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

Afortunadamente, el uso prudente de las variables de la 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. en ASP.NET (sugerencia: no utilizará el almacenamiento en proceso).

Para evitar esencialmente el resto de los inconvenientes de la sesión, recomiendo que implemente un objeto para almacenar los datos de su sesión, así como algunas capacidades simples de administración de objetos de sesión. Luego constrúyalos en un descendiente de la clase de Página y use esta clase de Página descendente para todas sus páginas. Entonces es un asunto simple acceder a los datos de su 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 permitirán 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!

Hasta donde yo 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 redirigen a un servidor web diferente, o en caso de un reciclaje del proceso de trabajo.

Una de las razones de su siniestra reputación es que los desarrolladores se apresuraron a utilizarla con literales de cadena en el código de UI (en lugar de una clase auxiliar como la suya) como claves de elementos, y terminan con una gran bolsa de estado promiscuo que no se puede probar. Algún tipo de envoltorio es un requisito de nivel de entrada para el uso de sesiones no perversas.

En cuanto a "La sesión es malvada" ... si estuviera desarrollando en ASP clásico, tendría que estar de acuerdo, pero ASP.NET/IIS hace un trabajo mucho mejor.

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

Otros pequeños tidbits de información que no necesitan persistencia a largo plazo utilizamos una combinación de cookies y viewstate.

Cuando desea almacenar información a la que se puede acceder globalmente en su aplicación web, una forma de hacerlo es mediante el atributo ThreadStatic . Esto convierte a un miembro static de una Class en un miembro que está compartido por el hilo actual, pero no por otros. 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 configurar el id del usuario al comienzo de cada solicitud en la propiedad ThreadStatic , y haga referencia a ella 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.

Creo que usar el objeto Session está bien en este caso, pero debes recordar que Session puede caducar si no hay actividad en el navegador por mucho tiempo ( HttpSessionState.Timeout determina en cuántos minutos el proveedor de estado de sesión termina la sesión), por lo que es mejor verificar el valor existencia antes de la vuelta:

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.");
}

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 almacenan en la página enviada al navegador, que luego se envía de nuevo al 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 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, yo diría que use 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 son " serializables " ;. Las mejores prácticas serían usar 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, una clave de sesión se mantiene en una cookie, o a través de la cadena de consulta, o utilizando otros métodos dependiendo de cómo esté configurada, y luego 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 quedar anonadadas durante una recarga del sitio, o se volverán casi inútiles en la mayoría de los entornos agrupados).

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

Todo lo que pones en el objeto de sesión permanece allí durante la duración de la sesión, a menos que se limpie. La mala gestión de la memoria almacenada usando inproc y stateerver lo obligará a escalar antes de lo necesario. Almacene solo una ID para la sesión / usuario en la sesión y cargue lo que sea necesario en el objeto de caché a pedido utilizando una clase auxiliar. De esa manera, puede ajustar su vida útil de acuerdo con la frecuencia con la que usamos esos datos. La próxima versión de asp.net puede tener un caché distribuido (rumor).

Sesión como malvado: No en ASP.NET, configurado correctamente. Sí, es ideal ser lo más apátrida posible, pero la realidad es que no se puede llegar desde aquí. Sin embargo, puede hacer que la sesión se comporte de manera que disminuya su impacto: notablemente StateServer o sesiones de base de datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top