domingo, 21 de octubre de 2007

(Membership - ApplicationID) Actualizacion de usuarios y ApplicationID

Como probablemente ya saben, asp.net cuenta con un sistema de perfiles y roles bastante completo y sencillo de utilizar en el 97% de los casos, ( les dejo AQUI un link que encontre muy util para entender el sistema de roles y membresias de asp.net). Sin embargo uno puede llegar a encontrarse con algunos problemas cuando decide salir de ese esquema pre establecido y ajustar las soluciones de acuerdo a sus necesidades.

Me encontre en un aprieto recientemente mientras desarrollaba una aplicacion en asp.net, a la hora de realizar un ABM de usuarios que utilizaran la pagina web; pues si bien asp.net es muy flexible y sencillo a la hora de implementar funcionalidades tipicas; es necesario hilar fino en algunas cosas para que todo funcione correctamente, y hay informacion que no siempre esta a mano para advertirnos de comportamientos con los que nos encontramos que son más que peculiares.

El problema me llego cuando quise implementar un update (y delete )de usuarios registrados. Como sabran, asp.net maneja la creacion de usuarios de manera completamente transparente. Uno simplemente agrega un control de registro de usuarios, y ASP.net se encarga de todo lo demás. El problema con esto, es que uno tiende a pensar que todo esta solucionado automaticamente, y se enfoca en otras cuestiones, ignorando entonces parte del funcioanmiento escencial que se mueve detrás de las bambalinas en el sitio que UNO mismo está construyendo.

Como decia, el problema se me sucito cuando quise hacer un update de usuarios registrados(la unica funcionalidad de "update" que vi en asp.net por defecto fue la de cambiar la contraseña, mientras que si uno desea realmente personalizar su sitio y tener la posibilidad de cambiar UserNames, preguntas secretas, direccion de mail y demas, es necesario hacerlo a "mano"). Entonces mediante Membership.GetUser(Username).ProviderUserKey es posible conseguir el GUID UserID para el usuario "Username"; con esto en mano era cuestion de, mediante SQL, realizar las consultas necesarias a la BD y realizar las modificaciones pertinentes, en las tablas pertinentes (aspnet_Membership, aspnet_Users, aspnet_profile(uso un proveedor de perfiles personalizado que voy a explicar en otro momento)).

A todo esto yo ya habia leido el post AQUI sobre la importancia de definir el nombre de la aplicacion a la hora de realizar un proyecto que va a ser implementado en un servidor remoto,o en una carpeta diferente a aquella en la que fue desarrollado, por lo que me asegure de hacerlo en el web.config.

Sucede que, a la hora de realizar la logica SQL necesaria para actualizar cada uno de los campos que deseaba en las tablas, me encontre con un UserID en la tabla de membresias, diferente a aquel en la de perfiles, y dos entradas por cada usuario en la tabla aspnet_Users, una para cada uno de los dos UserId anteriores, cada una con un ApplicationID diferente; y al ir a ver la tabla aspnet_Applications, me encontre con 2 aplicaciones: siendo una la "/", y la otra aquella con el nombre que yo habia definido, la razon?, la siguiente:

No alcanza con cambiar el nombre de la aplicacion en el web.config unicamente, es NECESARIO redefinir en el web.config cada uno de los proveedores que voy a utilizar (para membresia, roles y perfil) con el ApplicationName correspondiente; de otra forma, se utiliza la configuracion definida en el machine.config, en la que, por defecto, el applicationId es "/".

Las modificaciones al web.config, deberian ser algo como esto:



<system.web>
<membership><!--proveedor para membresia-->
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

connectionStringName="LocalSqlServer" enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="true"
applicationName="/MiAplicacionNombre" requiresUniqueEmail="false"
passwordFormat="Hashed" maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
</providers>
</membership>

<profile defaultProvider="TableProfileProvider"><!--proveedor para perfil-->
<providers>
<clear/>
<add name="TableProfileProvider"
type="Microsoft.Samples.SqlTableProfileProvider"
connectionStringName="LocalSQLServer"
table="Perfil"
applicationName="/MiAplicacionNombre"/>
</providers>
</profile>

<roleManager enabled="true"><!--proveedor para rol-->
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer"
applicationName="/MiAplicacionNombre"
type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add name="AspNetWindowsTokenRoleProvider"
applicationName="/MiAplicacionNombre"
type="System.Web.Security.WindowsTokenRoleProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</providers>
</roleManager>
<system.web>



Cabe aclarar que mi proveedor de perfil es diferente al que viene por defecto para asp.net, esto es debido a que aquel por defecto tiene una manera de almacenar los datos que los vuelve practicamente "inqueryables", puesto que deberiamos hacer un tratamiento bastante complejo de manejo de strings para poder recuperar los datos(prometo un detalle de esto en mi proximo post durante la semana que viene).

Pero todo lo demas deberia ser bastante similar en el caso generico.

Espero que esto les ayude a solucionar este inconveniente a todos aquellos que lo estén padeciendo, de igual forma que lo padeciera yo en su momento.

Saludos a todos y happy programming.

Leandro

No hay comentarios: