Esta es una articulo que se corresponde con uno anterior donde hable sobre las opciones de compartir session:
Particularmente en este articulo veremos la opción 1.1
OPCION 1: Cambiar el modo de estado de session (SessionState) a StateServer
OPCION 1.1: O cambiamos el ID de App (AppDomainAppId)
OPCION 1.2: O cambiamos el método que se obtiene el ID de Session (sessionIDManagerType)
Si bien hay varias opciones para compartir, la idea de hacerlo con el Servicio de estado de ASP.NET (StateServer) pero no tiene en modo nativo la forma de unificar el nombre de la aplicación y mas precisamente la propiedad AppDomainAppId que se utiliza dentro del servicio de estado para mantener el diccionario de variables de session por aplicación. Además mas abajo un ejemplo para descargar
Vamos paso por paso
Pasos que debemos cumplir para lograr el objetivo
- Todas las aplicaciones deben estar bajo el mismo dominio (para restricciones de cookie) IMPORTANTE!
En este caso mis pruebas fueron bajo localhost, pero funciona si cambas el dominio. Solo respetar que cada app esta bajo el mismo dominio - Establecer el SessionState en modo StateServer
- Configurar el servicio de estado de session (Importante)
- Establecer la misma machinekey
Incluso para compartir entre diferentes servidores cuando estas en un cluster
Ejemplo: Puedes encontrar varios generadores online - Establecer la misma nombre de la cookie
PAra poder compartir los datos deben ser ubicados (en la misma cookie de session). Acuerdense que es simplemente un identificador - IMPORTANTE El mismo nombre de la app (mmmm!??) propiedad AppDomainAppId
Por lo que hice este post donde explicamos como modificarla
Paso 1: Todas las aplicaciones deben estar bajo el mismo dominio
Aclaraciones, bajo el mismo dominio, y están configuradas como directorios virtuales. (mas abajo el ejemplo para descargar)
Para crear una de estas app
Mas adelante veremos como se obtiene el nombre de la app AppDomainAppId (Paso 6)
Paso 2: Establecer el SessionState en modo StateServer
Aqui utilizamos la seccion del web.config sessionState para establecer donde se ubicara nuestra variables de session
<sessionState cookieName="YODADemoApp"
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424" />
Aqui el primer comentario es que no tiene una forma de setear el nombre de la aplicación, siendo que en su correspondiente funcionalidad en Windows Azure si tiene! vamooosss que se puede modificar applicationName
http://msdn.microsoft.com/en-us/library/windowsazure/gg185682.aspx
PASO 3: Configurar el servicio de estado de sesión
Para que funcione al configuración del Paso 3 donde establecimos el modo StateServer y la ubicacion del servidor en la maquina local debemos habilitar ese servicio
Paso 4: Establecer la misma machinekey
Incluso para compartir entre diferentes servidores cuando estas en un cluster o en la misma maquina debes configurar la misma machinekey que se utiliza para:
“(…)Configura los algoritmos y las claves que se utilizan en el cifrado, descifrado y validación de los datos de autenticación de formularios y de los datos de estado de vista, así como para la identificación del estado de sesión fuera de proceso.(…)”
Ejemplo: Puedes encontrar varios generadores online
Paso 5: Establecer la misma nombre de la cookie
PAra que se guarde el valor de la session (un indentificdor) y que podamos obtenerlo a traves de multiples applicaciones en necesario que el nombre sea identico, por esta razon es conveniente modificarlo en la propiedad cookieName de sessionState
<sessionState cookieName="YODADemoApp"
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424" />
Paso 6: IMPORTANTE El mismo nombre de la app (mmmm!??)
Bueno hicimos todo lo anterior, pero cuando utilizamos StateServer para guardar los datos de session el proveedor utiliza el ApplicationName. El servicio es simplemente un ejecutable que tiene en cuenta el nombre de la aplicación
Como unificar el mismo nombre de ApplicationName para guardar el estado de session
Por aquí podemos leer que los proveedores de utilizan el nombre de la app para mantener el estado de session:
- Implementar un proveedor de almacén de estados de sesión
http://msdn.microsoft.com/en-us/library/ms178587.aspx (parte de ApplicationName)
(…) Para mantener el ámbito de la sesión, los proveedores de estados de sesión guardan por separado la información de sesión de cada aplicación. De esta forma, varias aplicaciones ASP.NET pueden usar el mismo origen de datos sin entrar en conflicto en caso de que se encuentren identificadores de sesión duplicados.
Dado que los proveedores de almacén de estados de sesión guardan por separado la información de sesión de cada aplicación, deberá asegurarse de que el esquema de datos, las consultas y las actualizaciones incluyen el nombre de la aplicación. Por ejemplo, se podría utilizar el comando siguiente para recuperar los datos de sesión de una base de datos.(…)
Cual es el nombre de mis app en este ejemplo
Las app que configure bajo el WebSite0 (dos websites ASP.NET Webforms y un app con ASP.NET MVC)
El árbol en el IIS quedo así en el ejemplo:
De donde sale este nombre?
Podes listar las app con la herramienta de lista de comandos appcmd pero los AppDomainAppId no se encuentran visible
Comando: appcmd list app
Pero ni aquí encontré el AppDomainAppId
Pero si listamos la configuración por sitio podemos ver el ID del sitio (un numero), con appcmd:
En la configuración avanzada mediante el Administrador de IIS
Entonces… como se arma el nombre?
El primer sitio que esta detenido “Default Web Site” es el primero que se creo en mi IIS local es el sitio numero 1, el segundo que cree para esta demo es WebSite0 que como es el 2 y el el raiz tiene el nombre:
/LM/W3SVC/2/ROOT
Por eso los nombres: /LM/W3SVC/2/ROOT/{nombre de la app}
Cambiar el AppDomainAppId
Primero antes de cambiarlo como lo leemos desde nuestro código:
- HttpRuntime.AppDomainAppId
Obtiene la identificación de aplicación del dominio de la aplicación donde se encuentra HttpRuntime.
http://msdn.microsoft.com/es-es/library/system.web.httpruntime.appdomainappid.aspx
Por eso veras en que el ejemplo que lo colocamos al nombre en un webcontrol literal llamado litAppDomainAppId:
private void RefrescarControles()
{
litAppDomainAppId.Text = HttpRuntime.AppDomainAppId;
Literal1.Text = SessionHelper.Variable1;
Literal2.Text = SessionHelper.Variable2;
}
Como cambiar
Si vemos la propiedad es estática y de solo lectura, así que no nos sirve ya que no podremos modificarla
Aquí nos ayudamos Reflection para obtener la variable privada dentro de HttRuntime que contiene el valor que es expuesto a traves de la propiedad AppDomainAppId. Ya han publicados ejemplos aquí y aquí, pero bueno es Reflection al fin y al cabo
El ejemplo seria en una método estático que nos ayude a modificar el nombre:
public static class SessionStateServerSharedHelper
{
public static void ChangeAppDomainAppId(string name)
{
FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
if (runtimeInfo == null) return;
HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null);
if (theRuntime == null) return;
FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.Instance | BindingFlags.NonPublic);
if (appNameInfo == null) return;
var appName = (String)appNameInfo.GetValue(theRuntime);
if (appName != "applicationName") appNameInfo.SetValue(theRuntime, name);
}
}
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
SessionStateServerSharedHelper.ChangeAppDomainAppId("YODADemoApp");
}
NOTA 1: El único problema que podemos encontrar es cuando los chicos de IT están monitoreando nuestros sitios y necesitan conocer en que app causo el problema, pero bueno hablando con ellos podremos detectarla con al nombre y la url que dio el error
NOTA 2: Cambiar metadata del IIS para unificar directorios: Si bien hay una forma de cambiar la metada es mas bien para compartir entre sitios web (aqui la idea que es que se mantenga la metadata y a nivel de aplicacion
- PRB: Estado de sesión se pierde en batería de servidores Web si utiliza SQL Server o el modo StateServer sesión
http://support.microsoft.com/kb/325056
El ejemplo para descargar
Sencillo para observar los pasos comentados. Se puede mejorar encapsulando este comportamiento y no estar compartiendo archivos de clase (eso lo dejo para mejorar por el que necesita utilizarlo). Lo puedes descargar directamente aquí
Además nos ayudamos para tener intellisense en las variables de session con una clase.
Por ejemplo para obtner el valor de la Variable1 de session utilizo
public static string Variable1
{
get
{
if (HttpContext.Current.Session["Variable1"] != null)
{
return HttpContext.Current.Session["Variable1"].ToString();
}
return string.Empty;
}
set {
HttpContext.Current.Session["Variable1"] = value;
}
}
Una mejora es que el nombre de la AppDomainAppId compartida sea configurada por el AppSettings pero como se mencione mas arriba deberías reiniciar la app para que lo tome. Esto se puede solventar con la opcion 1.2 sessionIDManagerType que será para el próximo post
Espero que les sirva de ayuda o guía.
, iis