Frage

Ich habe eine SearchController mit einer Aktion, die einige seit Jahren sucht und gibt eine Ergebnisseite ausführen kann. Die Suche kann überall von 1 bis 60 Sekunden dauern. Die URL für eine Suche ist eine HTTP-GET-Anforderung der Form: http://localhost/Search?my=query&is=fancy

Die Erfahrung ich suche ist ähnlich wie die vielen Reise-Websites, die es gibt. Ich möchte ein Zwischen "Loading ..." Seite zeigen, wo, ideal:

  1. Der Benutzer kann die Seite neu zu laden, ohne dass die Suche neu zu starten
  2. Sobald die Back-End-Suche beendet ist, wird der Benutzer auf die Ergebnisse umgeleitet
  3. Die Erfahrung degradiert für Browser mit JavaScript deaktiviert
  4. Der Zurück-Taste / Browser-History sollte nicht diese interstitielle Seite umfassen.
  5. Im Fall einer kurzen Suche (1 Sekunde), ist es nicht einen signifikanten Einfluss auf entweder die Zeit, um die Ergebnisse zu bekommen oder die Erfahrung (deutlich hässliche Seite blinkt, was auch immer)

Das ist die nice-to-have. Ich bin für alle Ideen offen! Danke.

War es hilfreich?

Lösung

Sie könnten es die folgende Art und Weise tun:

  • Sie die Suchanfrage (GET URL) mit AJAX
  • die Suche url die Ergebnisse nicht zurück, sondern gibt einige Json oder XML-Inhalte mit der URL der tatsächlichen Ergebnisse
  • die Client-Seite zeigt ein „loading ...“ Nachricht während für den AJAX-Aufruf warten zu beenden
  • leitet der Client-Seite auf der Ergebnisseite, wenn Sie fertig.

Ein Beispiel mit 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:)

Der Controller wäre so etwas wie:

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

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

Betrachten Sie es als Pseudo-Code: i. Es eigentlich nicht testen

Andere Tipps

Um es zu halten Javascript-less, können Sie die Suche in mehrere Aktionen durchbrechen.

Die erste Aktion (/ Suche /? Q = whodunit) funktioniert nur einige Validierung Ihrer Parameter (so wissen Sie, wenn Sie das Formular erneut angezeigt werden) und gibt dann eine Ansicht, die ein Meta-Refresh verwendet die Punkt Browser zurück auf die „echte“ Suchaktion.

Sie können dies implementieren mit zwei separaten Controller-Aktionen (zB Suche und Ergebnisse):

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

Aber das gibt Ihnen einige Tücken so weit wie erfrischend geht. So können Sie wieder verschmelzen sie wieder in einer einzigen Aktion, die sich des Prozesses Zweiphasensignal kann TempData verwendet wird.

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

Dies umfasst die Nummern 2, 3, 4 und 5 wohl.

Unterstützung umfassen für # 1 bedeutet, dass Sie die Ergebnisse der Suche speichern gehen entweder in der Sitzung, db, etc ..

In diesem Fall fügen Sie einfach Ihren gewünschten Cache implementatin als Teil der „hier eigentliche Suche Do“ bit, und fügen Sie ein Check-für-cached-Ergebnis die Lade Seite zu umgehen. z.

if (TempData[SearchLoadingPageSentKey]==null)

wird

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

Gute Frage. Ich kann bald eine ähnliche Lösung in asp.net MVC selbst implementieren müssen, aber ich glaube nicht, dass es eine grundsätzlich andere Implementierung als eine Webforms-basierte Lösung erfordern, von denen es verschiedene Beispiele im Netz:

Ich habe vorher eine Implementierung gebaut basierend auf dem ersten Link oben mit Web-Formularen. Der grundlegende Prozess ist:

  1. Erste Seite angefordert w / Suchparameter
  2. Diese Seite startet einen neuen Thread auf, die die lang andauernde Aufgabe ausführt
  3. Diese Seite leitet Benutzer auf eine „unter Prozess“ Seite, die einen HTTP-Refresh-Header gesetzt hat alle paar Sekunden
  4. nachladen
  5. Der Thread die Suche durchgeführt wird aktualisiert ein „globales“ statisches Such-progress-Objekt angibt, das% abgeschlossen, und die unter Prozess Seite liest aus es, den Fortschritt anzeigt. (Jede Suche nach einem GUID-ID in einem Hashtable gespeichert ist, so dass mehrere gleichzeitigen Suchvorgänge werden unterstützt)
  6. Nach Abschluss des Thread aktualisiert den Such Fortschritt als solche und wenn die unter Prozess Seite diesen erkennt, leitet es automatisch auf eine endgültige „Ergebnis“ Seite.

(Auf jeden Fall überprüfen, den zweiten Link von MSDN, ist es ganz andere Lösung, aber nicht, den ich habe nur überfliegt.)

Der Vorteil davon ist, dass es überhaupt nicht benötigt Javascript. Der größte Nachteil, dass ich mich vorstellen kann (aus der Sicht des Benutzers) ist, dass es nicht ganz „Web 2.0“ ist und Benutzer wird durch eine Reihe von Browser warten muß aktualisiert wird.

Etwas basierend auf @Jan Willem B AJAX-basierten Vorschlag soll eine brauchbare Alternative zu diesen Multi-Threaded-Wartezustand Muster sein. Welche am besten erfüllt Ihre Anforderungen ist etwas, das Sie auf eigene Faust zu entscheiden haben. Das Beispiel von aspfree.com ich geschrieben, obwohl die Mehrheit der Ihren Anforderungen entsprechen sollte und ebenso gut mit MVC als Web-Formulare arbeiten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top