Pregunta

Tengo un botón en mi formulario web. Al hacer clic en este botón, se realizará una HttpWebRequest durante el controlador de eventos onclick. Después de la solicitud, copiamos la respuesta de la solicitud en HttpContext.Current.Response y la enviamos al cliente.

Esta solicitud web puede llevar un tiempo (hasta 5 segundos, ya que genera un informe). Durante este tiempo, el usuario no tiene indicios de que algo esté sucediendo, excepto la barra de progreso del navegador y el ícono giratorio de IE (si están usando IE). Así que necesito un indicador de carga mientras esto sucede.

He intentado usar javascript que se activa durante el evento onclick del botón (usando OnClientClick) y aunque eso funciona, no sé cómo averiguar cuándo finaliza la solicitud web. Como solo enviamos la respuesta al cliente, no se realiza una devolución completa.

He intentado envolver el botón en un UpdatePanel y usar UpdateProgress, pero cuando enviamos la respuesta a HttpContext.Current.Response y llamamos Response.End (), recibimos un error en el javascript, ya que la respuesta no es está bien formado (estamos enviando una hoja de Excel para que el usuario la descargue).

Dado que estamos enviando un archivo para que los usuarios lo descarguen, no quiero abrir una ventana separada, ya que en IE obtendrían la barra de información que bloquea la descarga.

¿Alguna idea aquí?

¿Fue útil?

Solución

Como alternativa a la biblioteca profesional AJAX.NET, jQuery tiene una forma realmente agradable de hacerlo.

Eche un vistazo a este ejemplo de uso de un método de página .NET (si es posible en su escenario).

Define una llamada de método de página en jQuery, puede agregar su mensaje de carga ... en un div oculto.

Diga qué devolución de llamada desea devolver con éxito (es decir, cuando se genera su informe de 5 segundos) luego oculte la carga y maneje los datos.

Eche un vistazo a javascript en mi página de contacto para ver un ejemplo (ver la fuente).

  1. Tengo un botón en la página, agregue jQuery onClick.
  2. Al hacer clic en que muestra un div de carga oculto, realiza una llamada ajax a un método de página que toma los parámetros del formulario.
  3. El método de página envía correos electrónicos, etc., luego regresa al formulario en el método de JavaScript onSuccess que tengo allí.
  4. El onSuccess oculta la división de carga.

Otros consejos

Un truco simple que he usado en el pasado es redirigir a una página intermedia con una barra de progreso animada (gif) y luego hacer que esa página haga la publicación REAL de los datos. (o incluso abrir una capa con la animación y un mensaje cortés pidiéndole al usuario que espere un minuto o dos)

La simple respuesta del gif animado crea la ilusión para el usuario final de que la aplicación no está estancada y será más paciente.

Otro enfoque es entregar los datos a un subproceso de trabajo y devolverlos inmediatamente con un mensaje que indique que el informe se enviará por correo electrónico o estará disponible en " informes " sección del sitio cuando está listo. Sin embargo, este enfoque carece del beneficio de la notificación instantánea cuando se completa el informe.

Aquí está mi solución:

  1. Descargue y examine las muestras de la biblioteca profesional AJAX.NET gratuita.
  2. Escriba un método Ajax que cree su archivo y devuelva la ubicación del archivo como parámetro.
  3. Escriba su función del lado del cliente para llamar al método en el Paso 2. Cuando se llame a este método, muestre un indicador.
  4. Escriba un método de devolución de llamada del lado del cliente para ocultar el indicador y mostrar / descargar el archivo que solicitó el usuario.
  5. Agregue su función del lado del cliente llama a su elemento de botón.

Cuando finalice su método en el lado del servidor, se llamará a su devolución de llamada.

¡Espero que esto ayude!

La solución que presento aquí tiene como objetivo mostrar un método para permitir que " Cargando ... " cuadro que aparece mientras procesa en el lado del servidor y desaparece cuando se completa el procesamiento en el lado del servidor.

Haré esto con la maquinaria AJAX muy básica (probada en FF, pero IE también debería estar bien), es decir, no usar un marco como Prototype o jQuery o Dojo, ya que no especificó su conocimiento sobre ellos.

Para permitirle comprender mejor el truco, el siguiente es solo un pequeño ejemplo y no pretende ser una solución lista para usar. Tiendo a no ser superficial, pero creo que un ejemplo más claro puede explicar mejor que muchas palabras.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>First Example</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <style>
            .hidden {
                display: none;
            }
            .loadingInProgress {
                color: #FFFFFF;
                width: 75px;
                background-color: #FF0000;
            }
        </style>
    <script type="text/javascript">
        var httpRequest;
        if (window.XMLHttpRequest) { // Mozilla, Safari, ...
            httpRequest = new XMLHttpRequest();
            httpRequest.overrideMimeType('text/xml');
        } else if (window.ActiveXObject) { // IE
            try {
                httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch (e) {
                try {
                    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch (e) {}
            }
        }

        if (!httpRequest) {
            alert('Giving up :( Cannot create an XMLHTTP instance');
        }

        httpRequest.onreadystatechange = function(){
            switch (httpRequest.readyState) {
            case 1: // Loading
                document.getElementById('loading').className = "loadingInProgress";
                break;
            case 4: // Complete
                document.getElementById('loading').className = "hidden";
                if (httpRequest.status == 200) {
                    // perfect!
                } else {
                    // there was a problem with the request,
                    // for example the response may be a 404 (Not Found)
                    // or 500 (Internal Server Error) response codes
                }
                break;
            }
        };

        function go() {
            httpRequest.open('GET', document.getElementById('form1').action, true);
            httpRequest.send('');
        }
    </script>

  </head>
  <body>
      <div id="loading" class="hidden">Loading...</div>
      <form id="form1" name="form1" action="doSomething.php">
          <input type="button" value="Click to submit:" onclick="go()" />
      </form>
  </body>
</html>

Como puede ver, hay un <div> que contiene el " Cargando ... " mensaje.

El principio es mostrar / ocultar el XMLHttpRequest dependiendo del readyState objeto onreadystatechange.

He usado el controlador action del Cache-control: no-cache para activar el cambio <=>.

El script php de back-end que uso (declarado como el formulario <=>) solo duerme (5), para permitir que " Cargando ... " mensaje aparece durante 5 segundos.

<?php
sleep(5);
header('Cache-Control: no-cache');
echo "OK";
?>

El encabezado <=> es necesario, ya que, por lo general, si no lo configura, el navegador almacenará en caché la respuesta evitando volver a enviar la solicitud si fuera necesario.

Una buena fuente para " empezar " La documentación de AJAX es Mozilla MDC .

Todo esto podría ser manejado mucho más suavemente por un marco de Javascript como Prototype, aprovechando su enfoque seguro para el navegador, ahorrándole horas de depuración.


Edit:

Elegí php porque no conozco ASP.NET ni ASP, perdón por eso.


Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top