MsgBox en ASP .NET Introducción Cuando programamos en ASP.NET, los programadores de aplicaciones Windows, muchas veces extrañamos la versatilidad de la función MsgBox de Visual Basic®, que sirve para mostrar un mensaje por pantalla o pedir la confirmación al usuario para realizar alguna tarea específica. En esta oportunidad, vamos a realizar un control que permite emular dicha función sobre ASP.NET. Antes de comenzar, debemos aclarar que el código expuesto, solo se ha probado en el navegador Microsoft Internet Explorer® y utilizamos JavaScript para mostrar los mensajes en el equipo cliente. También demostramos como disparar eventos en el servidor desde JavaScript. El .NET Framework nos permite agregar esta funcionalidad a nuestros controles Web personalizados a través de la interfase IPostBackEventHandler. Funcionamiento Cuando el control se prepara (método OnPreRender) envía código JavaScript al navegador, que tiene entre otras cosas, lo siguiente: window.attachEvent("onfocus", MsgBoxMostrarMensaje) Esto permite que nuestra función MsgBoxMostrarMensaje se ejecute cuando se toma el foco de la pagina. Dicha función evalúa el contenido de algunas variables y luego, si todavía no se ha mostrado el mensaje, lo hace y marca dicha variable para no mostrarlo de nuevo. En el caso de la confirmación, también ejecuta una función provista por el .NET Framework para disparar el evento en el servidor. La referencia a esa función lo obtenemos también cuando se prepara el control, con Page.GetPostBackEventReference. Finalmente en el método Render, enviamos a la página las variables mencionadas que harán que nuestra función JavaScript muestre el mensaje deseado. Bien, como un ejemplo vale más que mil palabras y los desarrolladores nos entendemos escribiendo código, vamos directamente a crear nuestro control. El ejemplo está escrito en Visual Basic .NET pero es lo bastante simple como para poder traducirlo a cualquier lenguaje de .NET sin problemas. Además comentamos todo el código para su fácil interpretación. Crear el Control MsgBox El control, que hereda de System.Web.UI.WebControls.WebControl e implementa la interfase IPostBackEventHandler tiene los siguientes miembros. • • • ShowMessage. Este método se utiliza para mostrar un mensaje. (Es el "alert" de JavaScript) ShowConfirmation. Este método se usa para mostrar un mensaje de confirmación que pide al usuario que se acepte o cancele. (Es el "confirm" de JavaScript) NoChoosed. Evento que se dispara en el servidor cuando el usuario eligió <Cancelar> en el mensaje de confirmación. • YesChoosed. Evento que se dispara en el servidor cuando el usuario eligió <Aceptar> en el mensaje de confirmación. 1. Abra Visual Studio .NET. 2. Cree una solución en blanco llamada MsgBoxTest. 3. Agregue a la solución un nuevo proyecto. Visual Basic .NET: Biblioteca de Clases, llamada MsgBox. 4. Agregue una referencia a System.Web.dll. 5. Renombre el archivo Class1.vb que se acaba de crear por MsgBox.vb y asegúrese que contenga lo siguiente. Option Explicit On Option Strict On Imports System.ComponentModel Imports System.Web.UI Imports System.Web.UI.WebControls Public Class MsgBox 'Heredo de WebControl Inherits System.Web.UI.WebControls.WebControl 'Implemento IPostBackEventHandler para poder enviar mensajes desde el código JavaScript Implements IPostBackEventHandler 'Acá se guarda el mensaje a mostrar Private _Message As String 'Acá se guarda la clave para poder identificar a que mensaje se responde. Private _Key As String 'Acá guardamos si se desea disparar el evento en el Si Private _PostBackOnYes As Boolean 'Y aquí si se desea disparar el evento en el No Private _PostBackOnNo As Boolean 'Definimos los eventos que puede disparar este control Public Event YesChoosed(ByVal sender As Object, ByVal Key As String) Public Event NoChoosed(ByVal sender As Object, ByVal Key As String) 'Este método se utiliza para mostrar un mensaje de confirmación. Public Sub ShowConfirmation(ByVal Message As String, ByVal Key As String, _ ByVal PostBackOnYes As Boolean, ByVal PostBackOnNo As Boolean) 'El ÑaÑa es para identificar que es un mensaje de confirmación (ver Render) _Message = "ÑaÑa" & Message _Key = Key _PostBackOnYes = PostBackOnYes _PostBackOnNo = PostBackOnNo End Sub 'Este método se usa para mostrar un mensaje simple Public Sub ShowMessage(ByVal Message As String) _Message = Message End Sub 'Preparamos el control para enviar la función javascript Protected Overrides Sub OnPreRender(ByVal e As EventArgs) If Not MyBase.Page.IsClientScriptBlockRegistered("MsgBox") Then 'Registro todo el script del control Page.RegisterClientScriptBlock("MsgBox", FuncionJava1()) End If End Sub Private Function FuncionJava1() As String 'Acá esta la clave de todo este ejemplo... 'Si no se dispara el evento en el Si, se vacía la variable. Dim miPostBackOnYes As String = "MsgBoxTextoMensaje="""";" 'Si no se dispara el evento en el No, se vacia la variable. Dim miPostBackOnNo As String = "MsgBoxTextoMensaje="""";" 'Dependiendo lo que se elija, hacemos referencia o no, a la función que ejecuta el postback. 'Además recordamos quien esta disparando el evento. (_Key) If _PostBackOnYes Then 'El .Net Framework guarda en miPostBackOnYes la llamada a la función 'javascript que dispara el evento miPostBackOnYes = Page.GetPostBackEventReference(Me, "Yes" & _Key) End If If _PostBackOnNo Then 'El .Net Framework guarda en miPostBackOnNo la llamada a la función 'javascript que dispara el evento miPostBackOnNo = Page.GetPostBackEventReference(Me, "No_" & _Key) End If 'Como se ve, se programa el evento onfocus del objeto window y se dispara la función. 'La función verifica si MsgBoxTextoMensaje esta vacía, si es así, no hace nada, de 'lo contrario muestra el cartel o la confirmación, y luego vacía la variable. 'En el caso de confirmación se dispara la función java guardada en 'miPostBackOnYes ó en miPostBackOnNo Return "<script language=""javascript""> " & _ "var MsgBoxTipoMensaje; " & _ "var MsgBoxTextoMensaje; " & _ "window.attachEvent(""onfocus"", MsgBoxMostrarMensaje); " & _ "function MsgBoxMostrarMensaje() { " & _ "if (MsgBoxTextoMensaje) { " & _ "if (MsgBoxTextoMensaje != """") { " & _ "if (MsgBoxTipoMensaje==2) {" & _ " alert(MsgBoxTextoMensaje); " & _ "} else {" & _ "if (confirm(MsgBoxTextoMensaje)) { " & _ miPostBackOnYes & _ "} else { " & _ miPostBackOnNo & _ "}} MsgBoxTextoMensaje=""""; " & _ " }}} </script>" End Function Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) 'Dibujamos el control If ModoDisenio(Me) Then 'Si estamos en tiempo diseño. Muestro el nombre del control. writer.Write(Me.ID) Else 'Estamos en tiempo de ejecución. Envió el script con el contenido 'de las variables de JavaScript que corresponda If _Message <> String.Empty Then 'Antes de hacer nada reemplazo los Enter por espacios, 'las comillas dobles por comillas simples. 'Sino lo hacemos, no sale el cartel en el navegador. Dim miSB As System.Text.StringBuilder System.Text.StringBuilder(_Message) miSB.Replace(Microsoft.VisualBasic.vbCr, " "c) miSB.Replace(Microsoft.VisualBasic.vbLf, " "c) miSB.Replace("""", "'"c) = New 'Verifico el tipo de mensaje If miSB.ToString.StartsWith("ÑaÑa") Then 'Es un mensaje de confirmación. (confirm) 'Envío solo el valor de las variables de JavaScript, la función ' se ejecutará cuando tome el foco la pagina. (Ver OnPreRender) Me.Page.Response.Write("<script>MsgBoxTipoMensaje=1; MsgBoxTextoMensaje=""" + _ miSB.ToString.Substring(4) + """;</script>") Else 'Es un mensaje común. (alert) 'Envío solo el valor de las variables de JavaScript, la función ' se ejecutará cuando tome el foco la pagina. (Ver OnPreRender) Me.Page.Response.Write("<script>MsgBoxTipoMensaje=2; MsgBoxTextoMensaje=""" + _ miSB.ToString + """;</script>") End If miSB = Nothing End If End If End Sub 'Función privada para verificar si el control esta en modo diseño. Private Shared Function ModoDisenio(ByVal QueControl As _ System.Web.UI.WebControls.WebControl) As Boolean Dim DesignMode As Boolean = False Try DesignMode = QueControl.Site.DesignMode Catch : End Try Return DesignMode End Function 'Este método se ejecuta cuando el usuario clic en aceptar o cancelar. Public Sub RaisePostBackEvent(ByVal eventArgument As String) _ Implements IPostBackEventHandler.RaisePostBackEvent Select Case eventArgument.Substring(0, 3) Case "Yes" 'Si eligió Aceptar la primera parte del argumento es Yes (Ver FuncionJava1) 'Disparo el evento en la página. Le envío en "Key" quien hizo la llamada RaiseEvent YesChoosed(Me, eventArgument.Substring(3)) Case "No_" 'Si eligió Aceptar la primera parte del argumento es No_ (Ver FuncionJava1) 'Disparo el evento en la página. Le envío en "Key" quien hizo la llamada RaiseEvent NoChoosed(Me, eventArgument.Substring(3)) End Select End Sub End Class Agregando un icono al control 1. Para identificar el control dentro del cuadro de herramientas es muy útil agregar un icono que lo diferencie de los demás. Cree una imagen de 16x16 y con el nombre MsgBox.bmp y guárdela en la misma carpeta donde se encuentra la clase MsgBox.vb. 2. Incluya la imagen en el proyecto y marque: Acción de generación: Recurso Incrustado. 3. Compile el proyecto desde el menú Generar -> Generar MsgBox. Probando el control El control ya esta terminado, ahora sólo tenemos que probarlo: 1. Agregue a la solución un nuevo proyecto. Visual Basic .NET: Aplicación Web ASP.NET, llamada MsgBoxTest. 2. En el explorador de soluciones, haga doble clic sobre WebForm1.aspx. 3. Haga clic con el botón secundario del Mouse sobre el Cuadro de Herramientas y elija personalizar cuadro de herramientas. 4. En la ficha Componentes de .Net Framework, elija examinar. 5. Busque el ensamble MsgBox.dll en la carpeta Bin del proyecto creado en el paso 1. 6. Asegúrese que el control MsgBox queden marcados y haga clic en Aceptar. 8. Una vez con el control en su cuadro de herramientas arrástrelo al WebForm1.aspx. No se preocupe por la ubicación dentro del la página, ya que en tiempo de ejecución no se verá, a cambio de eso se enviará al navegador el código necesario para mostrar los mensajes. 9. Arrastre dos botones a Webform1.aspx llamados button1 y button2 respectivamente. 10. Seleccione el control button1 y escriba Grabar en la propiedad Text. 11. Seleccione el control button2 y escriba Eliminar en la propiedad Text. 12. Pegue el siguiente el código dentro de la clase Webform1 en el archivo WebForm1.aspx.vb. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'Acá verifico que pueda grabar. '. '. 'Se encontró una condición que necesita confirmación del usuario... 'Se envía True y False como 2 últimos parámetros ya que en este ejemplo no se 'necesita hacer PostBack cuando el usuario elige cancelar. MsgBox1.ShowConfirmation("Este movimiento ya esta conciliado. Esta seguro que desea grabarlo ?", _ "GRABAR", True, False) End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 'Acá verifico que se pueda a eliminar.... ' ' 'Se encontró una condición que necesita confirmación del usuario... 'Se envía True y False como 2 últimos parámetros ya que en este ejemplo no se 'necesita hacer PostBack cuando el usuario elige cancelar. MsgBox1.ShowConfirmation("La eliminación de este registro, incluye eliminar todos _ los movimientos que dependen de él. Esta seguro que desea eliminarlo ?", "ELIMINAR", True, False) End Sub Private Sub MsgBox1_YesChoosed(ByVal sender As Object, ByVal Key As String) Handles MsgBox1.YesChoosed 'Key contiene la clave introducida cuando se llama al método ShowConfirmation. Select Case Key Case "GRABAR" 'Se confirmó que se desea grabar lo mismo, grabo... '. '. MsgBox1.ShowMessage("Datos grabados correctamente.") Case "ELIMINAR" 'Se confirmó que se desea eliminar lo mismo, elimino '. '. MsgBox1.ShowMessage("Registro eliminado.") End Select End Sub 'Private Sub MsgBox1_NoChoosed(ByVal sender As Object, ByVal Key As String) Handles MsgBox1.NoChoosed 'En este ejemplo no lo utilizamos. 'Pero si necesita realizar alguna acción cuando el usuario hace clic en No, debe escribirlo aquí. 'End Sub 13. Establezca MsgBoxTest como proyecto de inicio. 14. Ejecute la aplicación. Si no se cometieron errores, al hacer clic en grabar deberá obtener esto. 14. Y una vez aceptada la condición, se envía un nuevo mensaje. Conclusión Este es un simple ejemplo de como integrar código JavaScript con nuestros controles de servidor de ASP.NET. Quiero aclarar antes de despedirme, que debido a la facilidad de ASP.NET de programar para la Web al estilo de formularios Windows, muchos programadores (principalmente los que conocen poco las tecnologías de la Web) olvidan en que ambiente se esta desarrollando e intentan programar una pagina Web como si fuera un formulario Windows. Y en ese sentido este control puede colaborar aun más a esa confusión. Es por eso que recomiendo no abusar del uso del mismo y tener en cuenta que cada vez que se envía un mensaje de confirmación y el usuario hace clic en aceptar ó cancelar hay un ida y vuelta al servidor con todo lo que eso implica. Teniendo en cuenta esos factores, este control puede ser una manera muy útil de interactuar con el usuario desde el código del lado del servidor.