6

Tôi có một SearchController với một hành động có thể thực hiện một số tìm kiếm chạy dài và trả lại trang kết quả. Các tìm kiếm có thể mất từ ​​1 đến 60 giây. URL cho tìm kiếm là yêu cầu HTTP GET của biểu mẫu: http://localhost/Search?my=query&is=fancyLàm cách nào để triển khai trang "tải ..." xen kẽ trong ASP.NET MVC?

Trải nghiệm tôi đang tìm kiếm tương tự với nhiều trang web du lịch ở ngoài đó. Tôi muốn thể hiện sự trung gian "Loading ..." trang ở đâu, lý tưởng:

  1. Người dùng có thể tải lại trang web mà không cần khởi động lại tìm kiếm
  2. Khi tìm kiếm back-end xong, người sử dụng được chuyển hướng đến kết quả
  3. Trải nghiệm giảm cho các trình duyệt đã tắt JavaScript
  4. Lịch sử nút quay lại/trình duyệt không được bao gồm trang xen kẽ này.
  5. Trong trường hợp của một tìm kiếm ngắn (1 giây), nó không có một tác động đáng kể ở hai thời gian để có được kết quả HOẶC kinh nghiệm (đáng kể xấu xí nhấp nháy trang, bất cứ điều gì)

Những là những điều tốt đẹp. Tôi mở cửa cho tất cả các ý tưởng! Cảm ơn.

Trả lời

2

Bạn có thể làm điều đó theo cách sau:

  • làm theo yêu cầu tìm kiếm (url GET) với AJAX
  • url tìm kiếm không trả lại kết quả, nhưng trả về một số Json hoặc XML nội dung với URL của kết quả thực tế
  • trang khách hàng hiển thị thông báo "đang tải ..." trong khi đợi cuộc gọi AJAX kết thúc
  • trang khách hàng chuyển hướng đến trang kết quả khi hoàn tất.

Một ví dụ sử dụng 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> 

(chỉnh sửa :)

Bộ điều khiển sẽ là một cái gì đó như:

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

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

xem xét nó pseudo-code: tôi đã không thực sự kiểm tra nó.

5

Để duy trì javascript ít hơn, bạn có thể chia nhỏ tìm kiếm thành nhiều hành động.

Hành động đầu tiên (/ Search /? Q = whodunit) chỉ thực hiện một số xác nhận thông số của bạn trình duyệt quay trở lại hành động tìm kiếm "thực".

Bạn có thể thực hiện điều này với hai hành động điều khiển riêng biệt (chẳng hạn tìm kiếm và kết quả):

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

Nhưng điều này mang đến cho bạn một số snags như xa như sảng khoái đi. Vì vậy, bạn có thể tái hợp nhất chúng trở lại thành một hành động đơn lẻ có thể tự báo hiệu cho quy trình hai pha sử dụng 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(...); 
    } 
} 

này bao gồm các điểm 2, 3, 4 và 5. cho là

Để bao gồm hỗ trợ cho # 1 ngụ ý rằng bạn đang đi để lưu trữ các kết quả tìm kiếm hoặc trong phiên, db, vv

Trong trường hợp này, chỉ cần thêm bộ đệm triển khai bộ nhớ cache mong muốn của bạn như một phần của "Thực tế tìm kiếm ở đây" bit và thêm kết quả kiểm tra để lưu vào bộ nhớ cache để bỏ qua trang tải. ví dụ.

if (TempData[SearchLoadingPageSentKey]==null)

trở thành

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

2

Tốt câu hỏi. Tôi có thể sớm phải thực hiện một giải pháp tương tự trong asp.net MVC, nhưng tôi không nghĩ rằng nó sẽ yêu cầu triển khai cơ bản khác với giải pháp dựa trên web, trong đó có nhiều ví dụ khác nhau trên mạng:

trước đây tôi đã xây dựng một thực hiện dựa trên các liên kết đầu tiên ở trên với các hình thức web. Quá trình cơ bản là:

  1. trang ban đầu được yêu cầu w/tìm kiếm thông số
  2. Trang này khởi động một chủ đề mới, thực hiện nhiệm vụ kéo dài
  3. Trang này chuyển hướng người dùng đến một trang "theo quy trình" có tiêu đề làm mới http được đặt lại để tải lại sau vài giây
  4. Chủ đề thực hiện tìm kiếm sẽ cập nhật đối tượng tiến trình tìm kiếm tĩnh "toàn cầu" cho biết% complete và trang quá trình đọc từ đó, hiển thị tiến trình. (mỗi tìm kiếm được lưu trữ bởi một GUID id trong Hashtable, vì vậy nhiều tìm kiếm đồng thời được hỗ trợ)
  5. Sau khi hoàn thành chuỗi cập nhật tiến trình tìm kiếm như vậy và khi trang quá trình phát hiện điều này, nó chuyển hướng đến kết quả cuối cùng " trang.

(Chắc chắn kiểm tra các liên kết thứ hai từ MSDN, đó là giải pháp khá khác nhau, nhưng không phải là một tôi đã chỉ lướt qua.)

Lợi ích của việc này là nó không đòi hỏi Javascript cả. Hạn chế lớn nhất mà tôi có thể nghĩ đến (từ quan điểm của người dùng) là nó không hoàn toàn là "Web 2.0" và người dùng sẽ phải chờ qua một loạt các trình duyệt làm mới.

Điều gì đó dựa trên đề xuất dựa trên AJAX của @Jan Willem B phải là một lựa chọn khả thi cho mẫu trạng thái chờ đa luồng này. Mà tốt nhất đáp ứng yêu cầu của bạn là một cái gì đó bạn sẽ phải quyết định của riêng bạn. Ví dụ từ aspfree.com tôi đã đăng sẽ đáp ứng phần lớn các yêu cầu của bạn và làm việc tốt với MVC dưới dạng biểu mẫu Web.

Các vấn đề liên quan