Twitter Facebook RSS Feed

jueves, 19 de junio de 2008 a las 00:30hs por Gustavo Cantero (The Wolf)

Hace unos meses comenzamos a desarrollar para un cliente una aplicación web más o menos compleja, con .NET 3.5 y bastante uso de AJAX. En esta aplicación hay páginas que utilizan varios UpdatePanels, y algunos de estos realizan procesos complejos que pueden llegar a demorar varios segundos, es por esto que nuestro cliente nos pidió que, al iniciar estos procesos, se bloquee la página para que el usuario no pueda ejecutar ninguna otra acción en la misma hasta tanto no finalice el proceso pendiente. Obviamente no queríamos ejecutar un script «a mano» cada vez que se ejecutaba una acción y otro al finalizar la misma, así que buscamos la manera de automatizarlo un poco. Comenzamos buscando los eventos propios del motor de AJAX de Microsoft® y encontramos que podemos capturar los del RequestManager cuando inicia una petición al servidor y cuando la misma finaliza. Esto lo podemos hacer utilizando los métodos add_initializeRequest y add_endRequest de la instancia actual del PageRequestManager, la cual podemos obtener con el siguiente código: Sys.WebForms.PageRequestManager.getInstance().

En el primer evento mostrábamos un ModalPopUp (control que muestra una «ventana» en la página y deshabilita todos los demás controles de la misma) de la librería ASP.NET AJAX Control Toolkit de Microsoft®, el cual contenía un mensaje que decía «Aguarde un momento…», y en el segundo evento lo cerrábamos. A continuación se muestra como quedaba el PopUp en la página:

<cc1:modalpopupextender ID="mpeLoading" runat="server" BehaviorID="idmpeLoading" PopupControlID="pnlLoading" TargetControlID="btnLoading" EnableViewState="false" DropShadow="true" BackgroundCssClass="ModalBackground"></cc1:modalpopupextender><br />
<asp:panel ID="pnlLoading" runat="server" Width="300" Height="50" HorizontalAlign="Center" CssClass="ModalPopup" EnableViewState="false" Style="display: none"><br />
    <br />Aguarde un momento...</asp:panel>
<asp:button ID="btnLoading" runat="server" Style="display: none"></asp:button>

y acá está el código JavaScript:

function initializeRequest(sender, args){
    $find('idmpeLoading').show();
}
function endRequest(sender, args){
    $find('idmpeLoading').hide();
}
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(initializeRequest);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);

Cabe aclarar que la variable idmpeLoading del código anterior contiene el identificador del ModalPopUp a mostrar.
Hasta este punto todo funcionaba bien, el problema surgió cuando utilizamos paneles modales con UpdatePanels dentro, en ese momento la ventana con el mensaje «Aguarde un momento…» se «dibujaba» debajo del panel que estaba utilizando el usuario, no cumpliendo con su finalidad, ya que de esta manera no se deshabilitaban todos los controles de la página.
Paso siguiente revisamos el código del ModalPopUp (el mismo se puede bajar desde el mismo link que mostré antes) y encontramos que a los paneles se les establece un valor fijo en el estilo zIndex para mostrarlos sobre los demás controles. Luego revisamos las propiedades del objeto de JavaScript que representa el panel y encontramos que posee dos objetos interesantes: _backgroundElement y _foregroundElement. Estos representan los DIVs del fondo y del contenido de PopUp respectivamente, entonces para hacer que estos objetos de HTML se posicionen sobre todos los demás simplemente tenemos que incrementarles la propiedad zIndex de su estilo. Entonces, nuestro código JavaScript queda como se muestra a continuación:

function initializeRequest(sender, args){
    var mpeLoading = $find('idmpeLoading');
    mpeLoading.show();
    mpeLoading._backgroundElement.style.zIndex += 10;
    mpeLoading._foregroundElement.style.zIndex += 10;
}
function endRequest(sender, args){
    $find('idmpeLoading').hide();
}
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(initializeRequest);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);

Por último, para hacer que esta funcionalidad esté presente en todas las páginas de nuestra aplicación, lo agregamos en la página «master» del sitio, logrando que en cualquier página (que utilice esta master) posea la funcionalidad aquí descripta.

En la siguiente imagen muestro como queda una aplicación de ejemplo que cree con Visual Studio 2008 para este artículo:

A continuación dejo el proyecto con el código fuente para quien quiera utilizar esta utilidad:

6 comentarios »

  1. John David dice:

    Hola. Me encantó muchísimo el artículo, es bastante interesante. Lo probé y me funciona perfecto; pero una vez cambio a otra página o refresco deja de funcionar; tienen alguna idea de por qué puede haber sucedido?

  2. John David dice:

    Estuve revisando y resulta que luego de que se carga por primera vez la página, no sigue haciendo llamadas ni asincrónicas ni sincrónicas (ya no pasa por el load), sin embargo los update siguen funcionando y demás; Alguien tiene una idea de cómo controlar esto?

  3. refugio13 dice:

    Hola,

    No se si me podran ayudar. Por si acaso les comento:

    Tengo una pantalla de mantenimiento en asp.net(vb) y Atlas. Y tengo que migrarla a ajax. He encontrado algunos manuales para ello(http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/ajax/documentation/Migration_Guide_CTP_to_RTM.aspx), pero despues de cambiar todo lo que se supone me da el siguiente error:

    Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.

    Parser Error Message: Could not load file or assembly ‘Microsoft.Web.Preview’ or one of its dependencies. The system cannot find the file specified.

    Esto es por que no tengo esas dll-s. Donde puedo conseguirlas?
    De todas maneras me gustaria saber si tienen o me podrian decir mas claramente como cambiar de atlas a ajax (mi nivel de ingles es bastante bajo, por lo cual mis modificaciones han sido un poco a ojo)

    Muchas gracias, un Saludo

    Refugio13

  4. Luis dice:

    Buenas compañero el ejemplo q esta no me sirve en vs 2005 si me podrias ayudar se lo agradeceria

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.