Pregunta

Tengo un SearchController con una acción que puede ejecutar algunas búsquedas de larga duración y devolver una página de resultados. Las búsquedas pueden llevar de 1 a 60 segundos. La URL para una búsqueda es una solicitud HTTP GET del formulario: http://localhost/Search?my=query&is=fancy

La experiencia que estoy buscando es similar a los muchos sitios de viajes que existen. Me gustaría mostrar un intermedio '' Cargando ... '' página donde, idealmente:

  1. El usuario puede volver a cargar la página sin reiniciar la búsqueda
  2. Una vez que finaliza la búsqueda de fondo, el usuario es redirigido a los resultados
  3. La experiencia se degrada para los navegadores con JavaScript deshabilitado
  4. El botón de retroceso / historial del navegador no debe incluir esta página intersticial.
  5. En el caso de una búsqueda corta (1 segundo), no tiene un impacto significativo en el tiempo para llegar a los resultados O en la experiencia (parpadeos de página significativamente feos, lo que sea)

Esos son buenos para tener. Estoy abierto a todas las ideas! Gracias.

¿Fue útil?

Solución

Puede hacerlo de la siguiente manera:

  • haga la solicitud de búsqueda (la URL GET) con AJAX
  • la URL de búsqueda no devuelve los resultados, pero devuelve contenido Json o XML con la URL de los resultados reales
  • la página del cliente muestra un " cargando ... " mensaje mientras espera que finalice la llamada AJAX
  • la página del cliente redirige a la página de resultados cuando finaliza.

Un ejemplo usando jquery:

<div id="loading" style="display: none">
  Loading...
</div>
<a href="javascript:void(0);" 
  onclick="searchFor('something')">Search for something</a>

<script type="text/javascript">
  function searchFor(what) {
    $('#loading').fadeIn();
    $.ajax({ 
      type: 'GET', 
      url: 'search?query=' + what, 
      success: function(data) { 
        location.href = data.ResultsUrl; 
      } 
    });        
  }
</script>

(editar :)

El controlador sería algo así como:

public class SearchController 
{
  public ActionResult Query(string q) 
  {
    Session("searchresults") = performSearch();
    return Json(new { ResultsUrl = 'Results'});
  }

  public ActionResult Results()
  {
    return View(Session("searchresults"));
  }
}

Considérelo pseudocódigo: en realidad no lo probé.

Otros consejos

Para mantenerlo sin javascript, puede dividir la búsqueda en varias acciones.

La primera acción (/ Buscar /? q = whodunit) solo valida algunos de sus parámetros (para que sepa si necesita volver a mostrar el formulario) y luego devuelve una vista que utiliza una meta-actualización para señalar el navegador de vuelta al " real " acción de búsqueda.

Puede implementar esto con dos acciones de controlador separadas (por ejemplo, Buscar y Resultados):

public ActionResult Search(string q)
{
    if (Validate(q))
    {
        string resultsUrl = Url.Action("Results", new { q = q });
        return View("ResultsLoading", new ResultsLoadingModel(resultsUrl));
    }
    else
    {
        return ShowSearchForm(...);
    }
}

bool Validate(string q)
{
    // Validate
}

public ActionResult Results(string q)
{
    if (Validate(q))
    {
        // Do Search and return View
    }
    else
    {
        return ShowSearchForm(...);
    }
}

Pero esto le da algunos inconvenientes en cuanto a refrescarse. Por lo tanto, puede volver a fusionarlos en una sola acción que puede indicar el proceso de dos fases utilizando TempData.

static string SearchLoadingPageSentKey = "Look at me, I'm a magic string!";

public ActionResult Search(string q)
{
    if (Validate(q))
    {
        if (TempData[SearchLoadingPageSentKey]==null)
        {
            TempData[SearchLoadingPageSentKey] = true;
            string resultsUrl = Url.Action("Search", new { q = q });
            return View("ResultsLoading", new ResultsLoadingModel(resultsUrl));
        }
        else
        {
            // Do actual search here
            return View("SearchResults", model);
        }
    }
    else
    {
        return ShowSearchForm(...);
    }
}

Esto cubre los puntos 2, 3, 4 y posiblemente 5.

Incluir soporte para el n. ° 1 implica que va a almacenar los resultados de la búsqueda en sesión, db, etc.

En este caso, simplemente agregue la implementación de caché deseada como parte de " Realice la búsqueda aquí " bit, y agregue un resultado de verificación de almacenamiento en caché para omitir la página de carga. por ejemplo,

if (TempData [SearchLoadingPageSentKey] == nulo)

se convierte

if (TempData [SearchLeadingPageSentKey] == null & amp; & amp;! SearchCache.ContainsKey (q))

Buena pregunta. Es posible que pronto tenga que implementar una solución similar en asp.net mvc, pero no creo que requiera una implementación fundamentalmente diferente a una solución basada en formularios web, de los cuales hay varios ejemplos en la red:

Anteriormente he creado una implementación basada en el primer enlace anterior con formularios web. El proceso básico es:

  1. Se solicita la página inicial con parámetros de búsqueda
  2. Esta página inicia un nuevo hilo que realiza la tarea de larga duración
  3. Esta página redirige al usuario a un " en proceso " página que tiene un encabezado de actualización http configurado para recargar cada dos segundos
  4. El hilo que realiza la búsqueda actualiza un " global " objeto de progreso de búsqueda estático que indica el% completado, y la página de proceso bajo lee de él, mostrando el progreso. (cada búsqueda se almacena mediante una identificación GUID en una tabla hash, por lo que se admiten múltiples búsquedas concurrentes)
  5. Una vez completado el hilo, se actualiza el progreso de búsqueda como tal y cuando la página en proceso lo detecta, lo redirige a un resultado final " página.

(Definitivamente revise el segundo enlace de MSDN, es una solución bastante diferente, pero no una que solo haya visto).

El beneficio de esto es que no requiere Javascript en absoluto. El mayor inconveniente que se me ocurre (desde la perspectiva de un usuario) es que no es del todo "Web 2.0". y los usuarios deberán esperar una serie de actualizaciones del navegador.

Algo basado en la sugerencia basada en AJAX de @Jan Willem B debería ser una alternativa viable a este patrón de estado de espera multiproceso. Lo que mejor se adapte a sus necesidades es algo que tendrá que decidir por su cuenta. Sin embargo, el ejemplo de aspfree.com que publiqué debe cumplir con la mayoría de sus requisitos y funcionar tan bien con MVC como los formularios web.

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