6

我有一個SearchController與一個動作,可以執行一些長時間運行的搜索並返回一個結果頁面。搜索可能需要1到60秒的時間。搜索的URL是以下格式的HTTP GET請求:http://localhost/Search?my=query&is=fancy如何在ASP.NET MVC中實現插頁式「加載...」頁面?

我正在尋找的體驗類似於那裏的許多旅遊網站。我想理想的顯示中間的「正在加載...」頁面,在這裏,

  1. 用戶可以重新載入頁面,而不一旦後端搜索完畢後重新啓動搜索
  2. ,用戶被重定向到結果
  3. JavaScript禁用的瀏覽器體驗下降
  4. 後退按鈕/瀏覽器歷史記錄不應包含此插頁式頁面。
  5. 在很短的搜索(1秒)的情況下,它並沒有在任一時間顯著影響,得到的結果或經驗(顯著醜陋的頁面閃爍,等等)

那些是很好的。我願意接受所有想法!謝謝。

回答

2

你能做到這一點的方式如下:

  • 與AJAX
  • 做搜索請求(GET 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")); 
    } 
} 

考慮它的僞代碼:我其實沒有測試它。

5

爲了讓它不再需要JavaScript,可以將搜索分解爲多個操作。

第一個操作(/ Search /?q = whodunit)只是對您的參數進行一些驗證(因此您知道是否需要重新顯示錶單),然後返回一個使用元刷新指向的視圖瀏覽器回到「真正的」搜索行動。

你可以用兩個獨立的控制器動作實現這一點(比如搜索和結果):

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以雙向過程的方式發出信號。

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等結果

在這種情況下,只需將您所需的緩存工具欄添加爲「Do actual search here」位的一部分,並添加check-for-cached-result來繞過加載頁面。例如

if (TempData[SearchLoadingPageSentKey]==null)

成爲

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

2

好問題。我可能很快必須自己在asp.net mvc中實現類似的解決方案,但我認爲它不需要與基於webforms的解決方案有着根本不同的實現方式,其中網上有各種示例:

我以前建立了基於上面Web表單的第一個鏈接的實現。其基本過程是:

  1. 初始頁面被請求瓦特/搜索參數
  2. 本頁面啓動一個新的線程執行長時間運行的任務
  3. 該網頁重定向用戶到「下的進程」頁其中有一個HTTP頭刷新設置爲每隔幾秒鐘
  4. 執行搜索線程加載更新了「全局」靜態搜索進度指示%完成目標,並在過程中頁面從中讀取,顯示進度。 (每個搜索都通過GUID ID存儲在Hashtable中,因此支持多個併發搜索)
  5. 一旦完成,線程更新搜索進度,並且當進程頁面檢測到這一點時,它將重定向到最終的「結果「頁面。

(當然檢查從MSDN的第二個鏈接,這是相當不同的解決方案,而不是一個我只是掠過。)

這樣做的好處是,它不需要JavaScript的。我能想到的最大的缺點(從用戶的角度看)是,它不是完全的「Web 2.0」的用戶將必須通過一系列等待瀏覽器刷新。

基於@Jan的東西Willem B的基於AJAX的建議應該是這種多線程等待狀態模式的可行替代方案。最符合您的要求是你必須要在你自己的決定。從aspfree.com的例子我張貼應該滿足,雖然大多數的按照您的要求爲MVC Web表單一樣好。