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表单一样好。