LastUpdateUser y LastUpdateDate en capa de negocios

Desde los primeros programitas que desarrollé, algo que me ha gustado tener y que, en más de una ocasión me ha servido para descubrir algún que otro problemilla ha sido guardar en las tablas de la base de datos los campos LastUpdateUser y LastUpdateDate con la finalidad de almacenar el usuario y la fecha de la última modificación. Este proceso, ya desde los tiempos de VB5 era un proceso bastante sencillo desde cualquier apartado de la aplicación, fuese un fichero .EXE o una .DLL. En principio, si la memoria no me falla, sólo había que hacer una llamada a la función GetUserName de la librería advapi32.dll.

Ha cambiado todo bastante desde aquellos tiempos y, lo más importante, ha cambiado el entorno de trabajo. Ahora ya no hace falta hacer llamadas a las API, o mejor dicho, sí pero muchísimo más sencillo que antaño. En el namespace System nos encontramos con una clase muy útil, Environment que incluye entre otras cosas, una propiedad UserName que nos devuelve el nombre de usuario que ha iniciado la sesión en Windows. Hasta aquí está todo bien, siempre que estemos trabajando en un entorno WinForms y siempre que la aplicación completa esté siendo ejecutada en la máquina del cliente.

En ASP.NET el problema es bien distinto dependiendo del escenario y realmente es uno bastante frecuente puesto que pocas son las aplicaciones ya que incluyen en el mismo proyecto la lógica de negocios y de presentación juntas.

¿Dónde nos encontramos realmente el problema?. Como siempre, intento explicarlo con un ejemplo. Pongamos que tenemos una solución con dos proyectos: Web como capa de presentación y BAL como capa de negocios. Ya tenemos montados (y funcionando) todo el tema de membresías y usuarios para poder acceder. Desde la Web sí que podemos tener el nombre del usuario actual

   1: string usuarioActual = User.Identity.Name;

pero sólo desde la web. Si necesitamos tener el mismo dato desde la capa de negocios, deberíamos ir pasando este dato como parámetro en cualquiera de los métodos que alteren datos.

   1: GuardaDatos(dato1,dato2,...,usuarioActual);

¿No quedaría mucho mejor que este dato lo tuviésemos ya en la capa de negocio para hacer algo similar a lo siguiente?:

   1: public void GuardaDatos(string dato1, int dato2)
   2: {
   3:     ...
   4:     c.Dato1 = dato1;
   5:     c.Dato2 = dato2;
   6:     c.LastUpdateUser = xxxx;
   7:     c.LastUpdateDate = System.DateTime.Now;
   8:     ...
   9: }

El problema nos lo encontramos en lo que he denominado xxxx en el ejemplo, aunque para renombrarlo un poco, vamos a darle un nombre diferente creando, por ejemplo, una propiedad estática en una nueva clase a la que denominaremos Configuracion.

   1: namespace BAL
   2: {
   3:     public class Configuracion
   4:     {
   5:         private static string _usuario = "DESCONOCIDO";
   6:  
   7:         /// <summary>
   8:         /// Obtiene o establece el usuario identificado en la aplicación Web
   9:         /// </summary>
  10:         public static string UsuarioActual
  11:         {
  12:             get { return _usuario; }
  13:             set { _usuario = value; }
  14:         }
  15:     }
  16: }

Ahora, con esta clase, lo único que nos queda es establecer el valor de la propiedad UsuarioActual. Para ello, tendremos que crearnos un clase de aplicación global, es decir, el fichero Global.asax que nos permitirá capturar el evento AuthenticateRequest de la clase HttpApplication. De esta manera, cada vez que se realice una solicitud sobre cualquier página, estaremos estableciendo el valor de la propiedad UsuarioActual con el nombre del usuario (en el caso que haya sido satisfactoria la autenticación).

   1: protected void Application_AuthenticateRequest(object sender, EventArgs e)
   2: {
   3:     BAL.Configuracion.UsuarioActual =
   4:       Request.IsAuthenticated
   5:       ? User.Identity.Name
   6:       : "DESCONOCIDO";
   7: }

¡Cómo me gusta el operador ternario de C#!. Aprendí a usarlo en Java y creo que es de lo más cómodo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *