6

長時間実行される検索を実行して結果ページを返すことができるアクションを備えたSearchControllerがあります。検索には 1 ~ 60 秒かかります。検索用の URL は、次の形式の HTTP GET 要求です。http://localhost/Search?my=query&is=fancy

私が探している経験は、そこにある多くの旅行サイトに似ています. 理想的には、中間の「読み込み中...」ページを表示したいと思います。

  1. ユーザーは検索を再開せずにページをリロードできます
  2. バックエンド検索が完了すると、ユーザーは結果にリダイレクトされます
  3. JavaScript が無効になっているブラウザーのエクスペリエンスが低下する
  4. 戻るボタン/ブラウザの履歴には、このインタースティシャル ページを含めないでください。
  5. 短い検索 (1 秒) の場合、結果に到達するまでの時間やエクスペリエンスに大きな影響はありません (非常に醜いページが点滅するなど)。

それらは持っていると便利です。私はすべてのアイデアを受け入れます!ありがとう。

4

3 に答える 3

5

JavaScriptを使用しないようにするために、検索を複数のアクションに分割できます。

最初のアクション(/ Search /?q = whodunit)は、パラメーターの検証を行い(フォームを再表示する必要があるかどうかがわかります)、メタリフレッシュを使用してブラウザーを指すビューを返します。 「実際の」検索アクション。

これは、2つの別々のコントローラーアクション(検索と結果など)で実装できます。

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

しかし、これはさわやかなことに関してはあなたにいくつかの障害を与えます。したがって、TempDataを使用して2フェーズプロセスを通知できる単一のアクションにそれらを再マージできます。

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

これは、ポイント2、3、4、およびほぼ間違いなく5をカバーします。

#1のサポートを含めることは、検索結果をセッション、データベースなどに保存することを意味します。

この場合、「ここで実際の検索を実行」ビットの一部として目的のキャッシュ実装を追加し、キャッシュ結果のチェックを追加して、読み込みページをバイパスします。例えば

if (TempData[SearchLoadingPageSentKey]==null)

になります

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

于 2009-10-30T18:17:58.223 に答える
2

良い質問。私はすぐにasp.net mvcで同様のソリューションを実装する必要があるかもしれませんが、ネット上にさまざまな例があるWebフォームベースのソリューションとは根本的に異なる実装が必要になるとは思いません:

上記の最初のリンクに基づいて、Webフォームを使用して実装を以前に構築しました。基本的なプロセスは次のとおりです。

  1. 最初のページは検索パラメータでリクエストされます
  2. このページは、長時間実行タスクを実行する新しいスレッドを開始します
  3. このページは、数秒ごとにリロードするように設定された http 更新ヘッダーを持つ「処理中」のページにユーザーをリダイレクトします
  4. 検索を実行するスレッドは、% 完了を示す「グローバル」静的検索進行状況オブジェクトを更新し、進行状況を表示する進行中のページがそれを読み取ります。(各検索は GUID ID によって Hashtable に格納されるため、複数の同時検索がサポートされます)
  5. 完了すると、スレッドは検索の進行状況をそのまま更新し、処理中のページがこれを検出すると、最終的な「結果」ページにリダイレクトします。

(MSDN の 2 番目のリンクを必ず確認してください。これはまったく異なる解決策ですが、ざっと目を通しただけではありません。)

これの利点は、Javascript をまったく必要としないことです。(ユーザーの観点から) 私が考えることができる最大の欠点は、それが完全に "Web 2.0" ではないことであり、ユーザーは一連のブラウザーの更新を待つ必要があります。

@Jan Willem B の AJAX ベースの提案に基づくものは、このマルチスレッドの待機状態パターンの実行可能な代替手段になるはずです。どちらが要件に最も適しているかは、自分で決定する必要があります。私が投稿した aspfree.com の例は、要件の大部分を満たし、Web フォームと同様に MVC と同様に機能するはずです。

于 2009-10-30T18:55:33.593 に答える
2

次の方法で実行できます。

  • AJAX を使用して検索要求 (GET URL) を実行する
  • 検索 URL は結果を返しませんが、実際の結果の URL を含む Json または XML コンテンツを返します。
  • AJAX 呼び出しが完了するのを待っている間、クライアント ページに「読み込み中...」というメッセージが表示される
  • 終了すると、クライアント ページは結果ページにリダイレクトされます。

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>

(編集:)

コントローラーは次のようになります。

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

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

疑似コードと考えてください。実際にはテストしていません。

于 2009-10-30T17:47:33.997 に答える