Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problema con ASP.NET & Session State

Iniciado por BeRSeRKeR, 13 de Julio de 2007, 09:56:57 AM

« anterior - próximo »

BeRSeRKeR

Hola.

Ante todo decir que no estoy muy puesto en el desarrollo de aplicaciones web. :)

Estoy desarrollando una aplicación web haciendo uso de ASP.NET 2.0 y estoy teniendo problemas con el estado de la sesión. Resulta que las variables que almacenaba en el objeto Session se me pierden. Al final he descubierto (o creo haber descubierto) que la causa es la escritura en un archivo.

Parece ser que cada vez que se modifica el arbol de directorios (o un archivo) del AppDomain, el worker process se recicla y la sesión se resetea, con la consiguiente pérdida de los datos almacenados.

Para manejar el estado de la sesión estoy utilizando el modo por defecto (InProc) ya que parece ser que es el más rápido, aunque tiene estos efectos colaterales (parece que con los otros dos modos no ocurre).

La cuestión es si existe alguna forma de evitar ésto sin cambiar el modo de sesión. He pensado en prescindir del objeto Session pero necesito mantener ciertas variables para cada usuario (por ejemplo para saber qué artículos tiene en la cesta de la compra y algunos datos más). ¿Se podría tal vez mantener una tabla hash que emule la sesión estándar de ASP.NET?. ¿Qué sistema utilizáis vosotros?.

Gracias.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

shephiroth

Me suena que por cookies habia alguna cosilla.....recuerdo de una variable de tipo diccionario que simulase los hash.....aunque si buscas a estas alturas ya habra alguna variable tipo hash que te sirva.....busca a ver si usando cookies te sirve.

Diferencial

Yo uso session y no tengo esos problemas, dependiendo lo que vayas hacer en la pagina en cuestion puedes usar viewstate, y sino puedes mirarte las session pero que las maneje sql server. Pero esta ultima no lo he llegado a probar porque como te comento no me habia hecho falta, ademas se usa mas bien si necesitas distribuir una session de un usuario a otras aplicaciones. Al igual no comprendo bien exactamente el problema que planteas, porque justo a mi no me ha pasado.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

BeRSeRKeR

Perdón por haber tardado tanto en responder.

Por ahora voy a seguir utilizando la sesión de ASP pero evitaré escribir en archivos. :lol:

Por otro lado, tengo una cuestión sobre javascript. ¿Se puede saber el alto total del área cliente del navegador?. No me refiero al alto visible sino, además del área visible, el área que se puede visualizar si se hace scroll verticalmente (llamémosle el alto virtual del area cliente :)).

Muchas gracias.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Diferencial

Pues no se si te servira pero se me acaba de ocurrir una idea, debieras de coger y realizar un wrapper de todo el contenido algo asi:

<div id="AreaDeDibujo">
 Aqui dentro va todo el contenido incluido, si el area necesita la barra vertical para moverte.
</div>

y despues solo necesitas extraer el height del div como? pues getElementById("AreaDeDibujo").style.height y con restas puedes saber todo lo que necesitas saber, pero ahi ya no te ayudo (Bueno sino lo ves claro entonce si) :lol: Todabia no se si funcionara porque no lo he probado.
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

Diferencial

No sirve, lo he usado y no te devuelve valor alguno. Si le estableces un valor si que te lo devuelve pero claro no es lo que interesa, porque se supone que tiene que ir creciendo dependiendo el contenido.  :roll:
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

BeRSeRKeR

¡Odio la programación web!. ¡Odio no poder tener el control absoluto de la aplicación! :lol:

En fin, seguiré buscando alguna propiedad que me pueda servir. Aunque otra solución sería poder bloquear el scroll momentaneamente (desactivar las barras de desplazamiento) o simplemente mover la capa que tiene que cubrir la "pantalla" (cada vez que se detecte scroll) para que siempre esté cubriendo el área cliente.

Gracias.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Tei

El protocolo HTTP no soporta sesiones, asi que la facilidad de sesiones es creada en capa de aplicacion.  Si no te funciona como quieres, y necesitas un control absoluto. Puedes desactivar el soporte de tu plataforma (asp) y create tu propio soporte de sesiones. Probablemente usando una base de datos, en lugar de ficheros.
Un soporte de sesiones basado en base de datos escrito por ti normalmente hara lo que tu quieras. Aunque tendras que lidiar con algunos bugs de los navegadores, como el envio incosistente del path (habra veces que enviaran "aplicacion" y otras que enviaran "/aplicacion").
Lo que yo ni intentaria es dar soporte a usuarios que no quieran cookies. Sin cookies yo no me molestaria en dar soporte de sesion.

BeRSeRKeR

Hola de nuevo.

Resulta que estoy haciendo una cesta de la compra para una página web (escrita en ASP.NET) y me estoy encontrando con un problema.

Veamos, yo guardo en el objeto de sesión una lista donde almaceno los productos que el usuario va añadiendo a la cesta. Por supuesto también tiene la opción de eliminar los productos que no desee. Para manejar el tema de añadir y quitar productos utilizo javascript. Para ello tengo una capa donde escribo el contenido de la cesta de la compra.

Pues bien, el problema es que transcurrido un tiempo, me aparecen/desaparecen productos que yo no he insertado en la sesión actual. Son objetos que se insertaron en otras sesiones. En un principio pensé que el sistema de sesiones me estaba volviendo a jugar una mala pasada pero tras comprobar que la lista de productos de la cesta era correcta dentro de la sesión, llegué a la conclusión que el problema era que parte del contenido de la capa se queda en la caché del navegador (aunque no pondría la mano en el fuego). Esta teoría se ha reforzado más al desactivar la caché de la página con la línea:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Llevo varios minutos añadiendo y eliminando productos y de momento no ha dado problemas. Pero claro, es un poco bestia cepillarse la caché de toda la página, así que mi pregunta es si es posible desactivar la caché sólo de un componente de la página. En mi caso sería la capa que contiene el código de la cesta de la compra. Así de paso me evitaría el problema de que el usuario dé marcha atrás en la página y si ya había añadido un producto le muestre la cesta en el estado anterior. :)

En fin, a ver si me podéis echar un cable.

Muchas gracias.

PD: por cierto, parece que ésto sólo me pasa en IE6 e IE7, pero no en Firefox...
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Diferencial

¿Porque no haces toda la logica en el servidor? Si lo que quieres es que no te recargue toda la página por hacer un postback usa ajax. Hay una libreria que saco microsoft, que a base de updatepanels puedes hacer virguerias. Te dejo el link http://www.microsoft.com/downloads/details.aspx?FamilyID=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&displaylang=en de esta forma no te hace falta eliminar la cache de la página. Puedes usar tambien los ajax control toolkit, para hacer tu interfaz mucho más atractiva y funcinan con la libreria de microsoft http://www.codeplex.com/AtlasControlToolkit/Release/ProjectReleases.aspx?ReleaseId=4923 si quieres ver como funcionan puedes visitar esta página http://www.asp.net/ajax/control-toolkit/live/, y si eres de los que te gusta el peligro(Como a mi) puedes usar lo más nuevo que ha sacado microsoft para competir con flash(Silverlight), aqui te dejo unas librerias que te permite integrarlo con el vs2005 sin usar orcas http://www.microsoft.com/downloads/details.aspx?FamilyId=A5189BCB-EF81-4C12-9733-E294D13A58E6&displaylang=en
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.

BeRSeRKeR

Hola.

La verdad es que estoy utilizando Ajax pero a pelo. Lo que pasa es que muchas veces, al enviar el XMLHttpRequest, y teniendo un punto de ruptura en el archivo de código que recibe la petición (el aspx), resulta que dicho punto no salta, es decir, que en teoría el código que genera toda la cesta no le llega a javascript (aunque le llega algo, una lista de productos pertenecientes a otras sesiones, que no sé de dónde sale, seguramente de la caché).

Como digo ésto sólo me pasa en IE6/7 y no en Firefox, pero desgraciadamente el navegador mayoritario sigue siendo IE.

Así que probaré lo que me dices. Ya pondré mis dudas por aquí. A ver si logro solucionarlo porque llevo ya 3 días perdidos con este tema.

Gracias.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Vicente

Ber, prueba si eso a preguntar aquí:

http://madriddotnet.com/forums/default.aspx

Es el foro de usuarios de .NET de Madrid, hay unos cuantos máquinas de ASP.NET por allí.

Un saludo!

Vicente

BeRSeRKeR

Hey Vicente, supongo que al final acabaré preguntando por allí, pero en principio prefiero intentarlo aquí. :)

En cualquier caso os comento. Lo cierto es que después de seguir depurando la aplicación, me da que el problema no está en la caché.

Lo que está ocurriendo es que yo envío la petición XMLHttp al servidor pero parece ser que éste no la procesa (repito, sólo me pasa en IE y no siempre, pero cuando ocurre, se descoloca toda la cesta de la compra, claro) ya que pongo un punto de ruptura en el aspx que procesa la petición y no salta. Lo que no entiendo es que si la petición aparentemente no tiene éxito, ¡cómo es posible que se me esté actualizando el contenido de la cesta de la compra (con cosas que no deberían ser, of course!).

Explico un poco mejor el proceso que sigo.

El usuario tiene la opción de hacer clic en el botón "Añadir a la cesta" de un producto determinado.

Hecho ésto, aparece un cuadro de diálogo donde puede especificar la cantidad y la variante a comprar. Entonces, al pulsar el botón "Aceptar", se envía una petición XML (o sea, Ajax) al servidor.

Al servidor se le pasan ciertos datos del producto como la referencia, la cantidad y la variante. De esta forma tengo los datos suficientes para insertar el producto en la lista de la cesta de la compra (que se almacena en la sesión).

Entonces recorro la lista de productos que hay en la cesta y genero el código HTML, que es la respuesta que se envía al cliente. Así que hecho ésto, se recibe la respuesta en JavaScript y simplemente machaco el contenido de la capa que utilizo como contenedor de la cesta de la compra, con el código recién recibido desde el servidor.

A su vez, cada uno de los elementos de la cesta de la compra, tiene un pequeño botón que sirve para eliminar dicho producto de la cesta. Lo que hace este botón es que llama a una función JavaScript que a su vez lleva a cabo otra petición XML al servidor para que elimine de la lista de la cesta el producto indicado. Una vez más, y como antes, como respuesta se produce el código HTML que se introducirá en la capa correspondiente a la cesta de la compra.

Pues bien, como he dicho, la función JavaScript que lleva a cabo la petición se llama perfectamente, pero no así el aspx que procesa la petición. Y lo más raro es que la función JavaScript que recibe la respuesta sí que se llama.

Pongo un poco de código.

Con esta función se lleva a cabo la petición. Como véis es código típico que se utiliza en los ejemplos de Ajax. En este caso he puesto que la petición sea síncrona pero ocurre lo mismo si es asíncrona:

function sendRequest(url, mime, fnRequestManager)
{  
   http_request = 0;

   if (window.XMLHttpRequest)
   {
       http_request = new XMLHttpRequest();
       if (http_request.overrideMimeType)
       {
           http_request.overrideMimeType(mime);
       }
   }
   else if (window.ActiveXObject)
   {
       try
       {
           http_request = new ActiveXObject("Msxml2.XMLHTTP");
       }
       catch (e)
       {
           try
           {
               http_request = new ActiveXObject("Microsoft.XMLHTTP");
           }
           catch (e) {}
       }
   }

   if (!http_request)
   {
       alert('ERROR: Unable to create an instance of XMLHTTP');
       return false;
   }

   //http_request.onreadystatechange = fnRequestManager;
   http_request.open('GET', url, false);
   http_request.send(null);
   
   fnRequestManager();

   return true;
}


Esta es la función que envía la petición de eliminación de un producto de la cesta de la compra:

function onRemoveItemFromCartClicked(cartItemKey)
{
   sendRequest('RemoveItemFromCartRequest.aspx?key=' + cartItemKey, "text/plain", manageRemoveFromCartDlgRequest);    
}


Ahora la función "callback" fnRequestManager correspondiente a la eliminación de un producto de la cesta:

function manageRemoveFromCartDlgRequest()
{
   if (http_request.readyState == 4)
   {
       if (http_request.status == 200)
       {
           var responseText = http_request.responseText;

           var cartContent = document.getElementById('cartContent');
           
           cartContent.innerHTML = responseText;
       }
       else
       {
           alert('ERROR: unable to manage request');
       }
   }
}


Y finalmente el aspx que procesa la petición y genera la respuesta que contiene el código HTML que se inserta en la capa correspondiente a la cesta de la compra:

protected void Page_Load(object sender, EventArgs e)
{
string code = "";

string key = Request.QueryString["key"];

DataTable table = Session["cart"] as DataTable;

table.Rows.Remove(table.Rows.Find(key.Substring("cartItem-".Length)));

// Generamos el código para la cesta de la compra
code += ShoppingCartElement.EmitHtml(table);

// Reasginamos el carrito de la compra
Session["cart"] = table;

Response.Write(code);
}


O sea que recapitulando, en el caso de la eliminación de un producto, siempre se entra en "onRemoveItemFromCartClicked", siempre se entra en "sendRequest", no siempre se entra en "Page_Load" (lado servidor) y siempre (y esto es lo más extraño si resulta que no se está generando una respuesta) se entra en "manageRemoveFromCartDlgRequest".

En fín,  a ver si se os ocurre algo que pudiera estar causando ésto.

Muchas gracias.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

Bueno, al final he hecho caso a Diferencial y me he descargado la librería de Microsoft, ASP.NET AJAX.

Y la verdad es que está muy bien. Facilita mucho las cosas. Me ha agradado mucho el que se puedan pasar tipos de datos propios (clases, etc) del servidor al cliente y viceversa (gracias a JSON). Es bastante curioso poder utilizar tus propias clases C# en javascript (reflection rulezzz :)). Y además es mucho mejor y más rápido que andar analizando la respuesta en formato XML.

El caso es que he hecho una primera implementación de la cesta de la compra con esta librería (me ha llevado unos pocos minutos adaptar el código que tenía) y por ahora parece funcionar bien (¡cruzo los dedos! :lol:).

Lo único que no me entusiasma del todo es los métodos (del lado servidor) que sirven de enlace con JavaScript (PageMethods) tengan que ser estáticos (en las versiones anteriores parece que ésto no era así). Aunque por ahora no me supone un inconveniente.

En fin, eso es todo por ahora.

Gracias.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Diferencial

Pues lo curioso, es que estuve a punto de usar JSON porque es mucho más rápido, pero por no comerme la cabeza y estar haciendo pruebas y tal, lo deje usando solo los updatepanels, como veras tambien existe un objeto updatepanelprogress que lo enlazas con los updatepanels y puedes hacerte una plantilla de carga con un gif o lo que quieras. Existe una página que te permite hacerte tu propio gif de carga, y descargartelo aqui te la dejo http://www.ajaxload.info/ como utilidad es la leche  :P
PARA TENER COSAS QUE NUNCA HAS TENIDO, TENDRÁS QUE HACER COSAS QUE NUNCA HAS HECHO.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.