2011-12-20 61 views
6

跨搜索結果頁面保留表單發佈(視圖模型)結果的最佳方法是什麼?ASP.NET MVC RouteValueDictionary和複雜對象

我有一個包含複選框的搜索表單。這種形式是建立使用視圖模型像

public class SearchViewModel 
{ 
    public string Name { get; set; } 
    public string[] Colors { get; set; } 
} 

當這個視圖模型被調回我用價值觀來建立一個查詢(使用EF)。結果轉換爲PagedList。

public class SearchController : Controller 
    { 
    public ActionResult Index() 
    { 
     //this displays the search form. 
     return View(); 
    } 

    public ActionResult Results(string game, SearchViewModel vm) 
    { 
     //this displays the results 
     ViewBag.SearchViewModel = vm; 
     var matches = _repository.AsQueryable() 
      .ColorOr(vm.Colors) 
      .WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim())); 

      return View(matches.ToPagedList(1, 10)); 
    } 
} 

既然顯示結果,我想使用Html.PagedListPager和RouteValueDictionary來創建分頁。

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new RouteValueDictionary(ViewBag.SearchViewModel))) 

但是;創建的URL如下所示:

http://localhost:5139/search?Name=test&Colors=System.String[]&PageIndex=0 

Colors的值最終是類型而不是值。我希望的URL看起來更像:

http://localhost:5139/search?Name=test&Colors=[Blue,Pink,Yellow]&PageIndex=0 
  1. 什麼能夠保留整個搜索結果頁面表單POST(視圖模型)的結果,最好的方法是什麼?
  2. RouteValueDictionary是否支持複雜對象?
  3. 我應該使用類似unbinder
  4. 我會更好使用ViewData或會話嗎?
+0

哇。這是我確切的問題。 +1 – 2013-03-08 15:01:48

回答

2

我已經做了這樣的情況下,我覺得這有什麼簡單,但功能強大,被序列我視圖模型對象,以JSON(你的情況SearchViewModel),使用類似與得到的JSON字符串NewtonSoft JSON.net然後,通過zlib.netZlib.DeflateStream類對字符串進行簡單壓縮(您也可以使用類似AES Rijndael的東西,但無疑會更慢,並且首先需要速度),然後將結果Base64字符串傳遞到您的QueryString中。

然後,當你準備再次使用它時(它實際上是一個視圖狀態),只需解壓縮JSON字符串並將其從JSON反序列化到相應的.NET對象(再次在你的案例SearchViewModel)。

對於我來說,爲我提供了一種享受,而且不會因爲只有少數表單字段被序列化而導致無法管理的網址或任何真正可衡量的性能影響。

我將盡快詳細介紹代碼示例。

UPDATE:Code samples ...

這是我會做在您的特定方案:

Results(string, SearchViewModel)行動:

public ActionResult Results(string encryptedUrlViewModel, string game, SearchViewModel vm) 
{ 
    SearchViewModel searchUrlViewModel = null; 
    if (!string.IsNullOrEmpty(searchUrl)) { 
     // only first submission, no url view model set yet, so compress it and store.. 
     encryptedUrlViewModel = Convert.ToBase64String(
     DeflateStream.CompressString(JsonConvert.SerializeObject(vm))); 
     ViewBag.EncryptedUrlViewModel = encryptedUrlViewModel; 
    } 
    else { 
     var jsonUrlViewModel = DeflateStream.UncompressString(Convert.FromBase64String(encryptedUrlViewModel)); 
     searchUrlViewModel = JsonConvert.DeserializeObject(jsonUrlViewModel, typeof(SearchViewModel)) as SearchViewModel; 
     // at this point you should have a serialized 'SearchViewModel' object 
     // ready to use which you can then tweak your query below with. 
    } 
    var matches = _repository.AsQueryable() 
     .ColorOr(vm.Colors) 
     .WhereIf(vm.Name.IsNotEmpty(), x => x.Name.Contains(vm.Name.Trim())); 

    return View(matches.ToPagedList(1, 10)); 
} 

鑑於:

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Results", new { encryptedUrlViewModel = ViewBag.EncryptedUrlViewModel })) 

的代碼可能需要一些調整,未經檢驗在你的情況下,但它會是這樣的,最好的運氣:)

但是你應該真的考慮一下,如果你想在分頁的URL中攜帶用戶的請求,那麼可以考慮爲什麼表格不是作爲GET請求而不是作爲POST請求。任何你特別想要的理由POST?我認爲GET將正確地攜帶您的Colors陣列,但請確保您的視圖模型設置正確。 See this Haacked article for model binding to lists

+0

只是要清楚。如上所述,最簡單的解決方案是將表單方法從POST更改爲GET。 – detroitpro 2011-12-22 04:19:44

+1

哈哈.... doh。哦,我的手製作了編碼解決方案,以浪費。哦,以及:)你可能需要的東西就像它有一天.. =) – GONeale 2011-12-22 13:37:30

+0

進入這個有點晚,但面臨類似的挑戰。那麼你會將整個搜索表單+結果列表包裝在Html表單中以獲得正確的模型綁定?如果整個視圖處於窗體中,是搜索視圖模型的分頁部分,還是它是控制器操作的單獨參數? – 2012-11-26 18:51:15

1

我有同樣的問題,但與搜索參數。我們有一個顏色參數,它是搜索引擎使用的顏色名稱列表。所以你可以勾選黑色和藍色,結果包含黑色和藍色產品。

我結束了使用Unbound

using Unbound; 
Unbinder u = new Unbinder(); 

@Url.Action("Index", new RouteValueDictionary(u.Unbind(SearchParams))) 

導致的鏈接,如:

/MyRoute?color[0]=black&color[1]=blue