Question

J'ai un contrôleur de recherche avec une action capable d'exécuter des recherches de longue durée et de renvoyer une page de résultats. Les recherches peuvent durer de 1 à 60 secondes. L’URL d’une recherche est une requête HTTP GET de la forme suivante: http: // localhost / Search? My = query & is = fancy

L’expérience que je recherche est similaire à celle de nombreux sites de voyage. Je souhaite afficher un intermédiaire " Chargement ... " page où, idéalement:

  1. L'utilisateur peut recharger la page sans redémarrer la recherche
  2. Une fois la recherche d'arrière-plan terminée, l'utilisateur est redirigé vers les résultats
  3. L'expérience se dégrade pour les navigateurs avec JavaScript désactivé
  4. L'historique du bouton / du navigateur précédent ne doit pas inclure cette page interstitielle.
  5. Dans le cas d’une recherche courte (1 seconde), cela n’a pas d’impact significatif sur le temps nécessaire pour obtenir les résultats OU sur l’expérience (une page vraiment moche clignote, peu importe)

Ce sont de bons à avoir. Je suis ouvert à toutes les idées! Merci.

Était-ce utile?

La solution

Vous pouvez le faire de la manière suivante:

  • faire la demande de recherche (l'URL GET) avec AJAX
  • l'URL de recherche ne renvoie pas les résultats, mais renvoie du contenu Json ou XML avec l'URL des résultats réels
  • la page du client affiche un " chargement ... " message en attendant la fin de l'appel AJAX
  • la page client redirige vers la page de résultats lorsque vous avez terminé.

Un exemple utilisant 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:)

Le contrôleur ressemblerait à quelque chose comme:

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

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

Considérez-le comme un pseudo-code: je ne l'ai pas réellement testé.

Autres conseils

Afin de ne pas utiliser de code javascript, vous pouvez diviser la recherche en plusieurs actions.

La première action (/ Search /? q = whodunit) ne fait que valider vos paramètres (pour que vous sachiez si vous devez afficher à nouveau le formulaire), puis renvoie une vue qui utilise une méta-actualisation pour pointer le navigateur retourne à la " real " action de recherche.

Vous pouvez l'implémenter avec deux actions de contrôleur distinctes (par exemple, Recherche et Résultats):

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

Mais cela vous donne quelques problèmes en ce qui concerne le rafraîchissement. Vous pouvez donc les fusionner à nouveau en une seule action qui peut indiquer le processus en deux phases utilisant 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(...);
    }
}

Cela couvre les points 2, 3, 4 et sans doute 5.

Inclure la prise en charge de # 1 implique que vous stockiez les résultats de la recherche dans une session, une base de données, etc.

Dans ce cas, ajoutez simplement l’implémentation de cache souhaitée dans le cadre de la section "Effectuer une recherche réelle ici". et ajoutez un résultat de recherche de cache pour contourner la page de chargement. par exemple

if (TempData [SearchLoadingPageSentKey] == null)

devient

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

Bonne question. Je devrais peut-être bientôt mettre en œuvre moi-même une solution similaire dans asp.net mvc, mais je ne pense pas que cela nécessiterait une implémentation fondamentalement différente de celle d'une solution basée sur les formulaires Web, dont il existe divers exemples sur le net:

J'ai déjà construit une implémentation basée sur le premier lien ci-dessus avec les formulaires Web. Le processus de base est le suivant:

  1. La page initiale est demandée avec les paramètres de recherche
  2. Cette page démarre un nouveau thread qui exécute la tâche longue
  3. Cette page redirige l'utilisateur vers un " sous processus " page dont l'en-tête d'actualisation http est définie pour être rechargée toutes les quelques secondes
  4. Le fil effectuant la recherche met à jour un " global " L'objet statique search-progress indiquant le% achevé et la page de processus sous le lit, affichant la progression. (chaque recherche est stockée par un identifiant GUID dans une table de hachage, de sorte que plusieurs recherches simultanées sont prises en charge)
  5. Une fois l'opération terminée, le fil de discussion met à jour l'avancement de la recherche en tant que tel et lorsque la page de processus "under" le détecte, il redirige vers un "résultat" final. page.

(Vérifiez certainement le deuxième lien de MSDN, c'est une solution assez différente, mais pas une solution sur laquelle j'ai seulement écrémé.)

L'avantage de cela est qu'il ne nécessite pas du tout Javascript. Le plus gros inconvénient auquel je peux penser (du point de vue de l'utilisateur) est que ce n'est pas entièrement "Web 2.0". et les utilisateurs devront attendre une série de mises à jour du navigateur.

Quelque chose basé sur la suggestion AJAX de @Jan Willem B devrait être une alternative viable à ce modèle d’état d’attente à plusieurs threads. Ce qui vous convient le mieux est quelque chose que vous devrez choisir vous-même. L’exemple de aspfree.com que j’ai posté devrait cependant répondre à la majorité de vos besoins et fonctionner aussi bien avec les formulaires Web que MVC.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top