ASP.NET MVCにインタースティシャル「読み込み中」ページを実装するにはどうすればよいですか?
-
22-07-2019 - |
質問
長時間実行される検索を実行して結果ページを返すことができるアクションを持つ SearchController があります。検索には1〜60秒かかります。検索のURLは、次の形式のHTTP GETリクエストです: http:// localhost / Search?my = query& is = fancy
私が探している経験は、そこにある多くの旅行サイトに似ています。中間の「読み込み中...」を表示したいと思います。ここで、理想的:
- ユーザーは検索を再開せずにページをリロードできます
- バックエンド検索が終了すると、ユーザーは結果にリダイレクトされます
- JavaScriptが無効になっているブラウザでは、エクスペリエンスが低下します
- 戻るボタン/ブラウザの履歴には、このインタースティシャルページを含めないでください。
- 短い検索(1秒)の場合、結果に到達するまでの時間やエクスペリエンス(重大ないページフラッシュなど)に大きな影響はありません
これらは便利なものです。私はすべてのアイデアを受け入れています!ありがとう。
解決
次の方法で実行できます。
- 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"));
}
}
擬似コードを考慮してください。実際にはテストしませんでした。
他のヒント
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のサポートを含めることは、セッション、dbなどのいずれかに検索結果を保存することを意味します。
この場合、「ここで実際の検索を行う」の一部として、目的のキャッシュ実装を追加します。ビット、およびキャッシュ結果のチェックを追加して、読み込みページをバイパスします。例:
if(TempData [SearchLoadingPageSentKey] == null)
なる
if(TempData [SearchLeadingPageSentKey] == null&amp;&amp;!SearchCache.ContainsKey(q))
良い質問です。 asp.net mvcで同様のソリューションを自分ですぐに実装する必要があるかもしれませんが、ネット上にさまざまな例があるWebフォームベースのソリューションとは根本的に異なる実装が必要になるとは思いません。
- 長期実行タスクの実行 ASP.NETのプログレスバー(aspfree.com)
- パッテンの設計:非同期待機 ASP.NETの状態パターン(MSDN)
以前、上記の最初のリンクとWebフォームに基づいた実装を作成しました。基本的なプロセスは次のとおりです。
- 検索パラメーター付きの初期ページが要求されます
- このページは、長時間実行されるタスクを実行する新しいスレッドを起動します
- このページは、ユーザーを「処理中」にリダイレクトします。数秒ごとにリロードするように設定されたhttp更新ヘッダーを持つページ
- 検索を実行するスレッドは、「グローバル」を更新します;完了率を示す静的な検索進行オブジェクト。処理中のページがそれを読み取り、進行状況を表示します。 (各検索はHashtableのGUID IDによって保存されるため、複数の同時検索がサポートされます)
- スレッドが完了すると、検索プロセスが更新され、処理中のページがこれを検出すると、最終的な「結果」にリダイレクトされます。ページ。
(MSDNの2番目のリンクを必ず確認してください。これはまったく別のソリューションですが、私が精査しただけではありません。)
この利点は、Javascriptをまったく必要としないことです。 (ユーザーの観点から)私が考えることができる最大の欠点は、それが完全に「Web 2.0」ではないことです。ユーザーは一連のブラウザの更新を待つ必要があります。
@Jan Willem BのAJAXベースの提案に基づいたものは、このマルチスレッドの待機状態パターンの実行可能な代替物であるはずです。要件に最も合っているのは、自分で決める必要があるものです。私が投稿したaspfree.comの例は、要件の大部分を満たし、MVCとWebフォームで同様に機能するはずです。