Domanda

Ho un SearchController con un'azione che può eseguire alcune ricerche a lungo termine e restituire una pagina dei risultati. Le ricerche possono richiedere da 1 a 60 secondi. L'URL per una ricerca è una richiesta HTTP GET del modulo: http://localhost/Search?my=query&is=fancy

L'esperienza che sto cercando è simile ai numerosi siti di viaggi che ci sono. Vorrei mostrare un intermedio "Caricamento in corso ..." pagina in cui ideally:

  1. L'utente può ricaricare la pagina senza riavviare la ricerca
  2. Al termine della ricerca back-end, l'utente viene reindirizzato ai risultati
  3. L'esperienza peggiora per i browser con JavaScript disabilitato
  4. La cronologia del pulsante Indietro / browser non deve includere questa pagina interstiziale.
  5. Nel caso di una breve ricerca (1 secondo), non ha un impatto significativo né sul tempo necessario per raggiungere i risultati né sull'esperienza (lampeggi di pagina significativamente brutti, qualunque cosa)

Sono belli da avere. Sono aperto a tutte le idee! Grazie.

È stato utile?

Soluzione

Potresti farlo nel modo seguente:

  • esegui la richiesta di ricerca (l'URL GET) con AJAX
  • l'URL di ricerca non restituisce i risultati, ma restituisce alcuni contenuti Json o XML con l'URL dei risultati effettivi
  • la pagina del client mostra un " caricamento in corso ... " messaggio durante l'attesa del completamento della chiamata AJAX
  • la pagina client reindirizza alla pagina dei risultati al termine.

Un esempio che utilizza 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>

(edit:)

Il controller sarebbe qualcosa del tipo:

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

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

Consideralo pseudo-codice: in realtà non l'ho testato.

Altri suggerimenti

Per mantenerlo privo di javascript, è possibile suddividere la ricerca in più azioni.

La prima azione (/ Cerca /? q = whodunit) esegue solo una parte della convalida dei parametri (quindi sai se è necessario visualizzare nuovamente il modulo) e quindi restituisce una vista che utilizza un meta-aggiornamento per puntare il browser torna a " real " azione di ricerca.

Puoi implementarlo con due azioni separate del controller (ad esempio Ricerca e risultati):

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(...);
    }
}

Ma questo ti dà alcuni intoppi per quanto riguarda l'aggiornamento. Quindi puoi riunirli nuovamente in un'unica azione che può segnalare se stesso del processo in due fasi utilizzando 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(...);
    }
}

Questo riguarda i punti 2, 3, 4 e probabilmente 5.

Includere il supporto per il n. 1 implica che memorizzerai i risultati della ricerca in sessione, in db, ecc.

In questo caso, aggiungi semplicemente l'implementazione della cache desiderata come parte di " Effettua la ricerca effettiva qui " bit e aggiungi un risultato di verifica della cache per ignorare la pagina di caricamento. per es.

if (TempData [SearchLoadingPageSentKey] == null)

diventa

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

Buona domanda. Potrei presto dover implementare una soluzione simile in asp.net mvc da solo, ma non credo che richiederebbe un'implementazione fondamentalmente diversa rispetto a una soluzione basata su webform, di cui ci sono vari esempi in rete:

Ho già realizzato un'implementazione basata sul primo link sopra con i moduli web. Il processo di base è:

  1. Pagina iniziale richiesta con parametri di ricerca
  2. Questa pagina avvia un nuovo thread che esegue l'attività di lunga durata
  3. Questa pagina reindirizza l'utente a un " in elaborazione " pagina con un'intestazione di aggiornamento http impostata per ricaricare ogni paio di secondi
  4. Il thread che esegue la ricerca aggiorna un " global " oggetto statico di avanzamento della ricerca che indica% completato e la pagina di processo in corso legge da esso, visualizzando l'avanzamento. (ogni ricerca è memorizzata da un ID GUID in un Hashtable, quindi sono supportate più ricerche simultanee)
  5. Una volta completato, il thread aggiorna l'avanzamento della ricerca in quanto tale e quando la pagina di processo in corso lo rileva, reindirizza a un "risultato" finale ". pagina.

(Sicuramente controlla il secondo link da MSDN, è una soluzione abbastanza diversa, ma non quella su cui ho solo sfogliato.)

Il vantaggio di questo è che non richiede affatto Javascript. Il più grande svantaggio che mi viene in mente (dal punto di vista di un utente) è che non è interamente "Web 2.0" e gli utenti dovranno attendere una serie di aggiornamenti del browser.

Qualcosa basato sul suggerimento AJAX di @Jan Willem B dovrebbe essere una valida alternativa a questo modello di stato di attesa multi-thread. Quello che soddisfa meglio le tue esigenze è qualcosa che dovrai decidere da solo. L'esempio di aspfree.com che ho pubblicato dovrebbe soddisfare la maggior parte delle tue esigenze e funzionare altrettanto bene con MVC che con i moduli Web.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top