2011-05-01 40 views
27

我想我錯過了關於MVC表單工作原理的一些基礎知識。我在我的主頁上有一個搜索表單,其中有五六個不同的字段供用戶搜索。所以我有這個發佈到我的結果行動就好了。結果操作如下所示:MVC 3表單發佈並保留模型數據

[HttpPost] 
public ActionResult Results(SearchModel model) 
{ 
    ResultsModel results = new ResultsModel(); 
    results.ResultList = SearchManager.Search(model).ToList(); 

    return View("Results", results); 
} 

我簡化了上述方法,但這個想法是相同的。所以這一切都很好。我的結果頁面顯示了結果的列表,我的用戶是在以下網址:

http://www.site.com/results

所以......現在我想要做的事很常見。結果頁面上有兩個下拉列表。 「排序」和「每頁結果數量」。我該怎麼做,並將全套模型數據發送回控制器,以便我可以使用新參數進行查詢?實際上,SearchModel類擁有大約60個不同的字段。潛在的所有數據都可以包含在模型中。你如何堅持到一個頁面「回發」?

同樣的問題讓我對如何進行分頁以及有點難過。我的分頁鏈接會去一個網址,如:

http://www.site.com/results/2

但是,假設我們在響應GET請求(我不想在查詢字符串數據的60場)和模型數據在GET請求之間傳遞,我知道情況並非如此。如上所述,我想我錯過了一些關於MVC 3,模型和表單帖子的基礎知識。

任何人都可以幫助我指出正確的方向嗎?我很樂意根據需要編輯/更新這篇文章,以澄清事情。

編輯:我也想指出,我想避免將視圖模型存儲在Session變量中。這個網站最終最終會在一個網絡農場中實現負載均衡,我真的想盡可能避免使用Session。但是,如果它是唯一的選擇,我將配置另一個會話狀態提供程序,但我不想。

+0

嗯,我想聽聽一些關於這方面的專家意見,但也有可能讓我有選擇直接或間接地通過TempData掌握Session。其他選項是在結果頁面上有大量隱藏字段。 – 2011-05-01 15:54:55

+0

對不起,那個帶隱藏字段的部分是無稽之談。最簡潔的方法是使用tempdata。 – 2011-05-01 16:06:19

+0

它仍然感覺像2001 :( – andrew 2012-06-01 00:15:01

回答

15

您可以將當前的SearchModel參數添加到表單的路由值。 BeginForm的幾個版本允許你傳遞一個對象/ RouteValuesDictionary。

@Html.BeginForm("Action", "Controller", new { SearchModel = Model }, FormMethod.Post) 

這應該傳遞您當前的SearchModel值,以便您可以重新使用它們以獲取下一頁。您需要定義一個控制器操作,以接受任何當前頁面的表單值以及SearchModel。

我沒有使用表單帖子完成此任務,但是從我所做的以及從文檔所說的內容來看,這是我要開始的地方。當然,這也意味着頁面上的每個頁面「鏈接」都需要發佈信息。如果用戶希望能夠在瀏覽器中使用「後退」按鈕,那真的很不方便。

在這種情況下,您可以嘗試定義允許頁碼顯示爲URL的一部分的路由 - 「操作/控制器/ {頁面}」。但是,我不確定該表單如何發揮作用,因爲該表單正在發佈帖子。

迴應評論:

是的,你可以使用路由值的SearchModel添加到每個網頁鏈接,但正如我在評論說,如上所述,由於鏈接將做「得到,」你的用戶會請參閱序列化的SearchModel作爲鏈接的一部分。

無論採用哪種方式,使用路徑值都是您在不使用隱藏字段,會話或TempData的情況下取回原始SearchModel的答案。

+0

如果我找不到其他解決方案,我會仔細研究,但我想避免表單帖子,哈哈。我覺得用戶希望能夠在沒有表單文章的情況下瀏覽結果(因此他們可以刷新或使用後退按鈕),並且能夠在不擔心會話超時的情況下進行分頁。也許這只是MVC的一個缺點。我傾向於在這一點上使用GET,並讓URL變得有點混亂。 – Scott 2011-05-01 16:53:33

2

我在這裏想到的一個選項是實現一個支持充當自定義會話提供者(即Memcached或Windows Server AppFabric)的分佈式緩存系統,從而允許我在TempData(和Session)中使用一個負載均衡的環境如下:

[HttpPost] 
public ActionResult Results(SearchModel model) 
{ 
    ResultsModel results = new ResultsModel(); 
    results.ResultList = SearchManager.Search(model).ToList(); 

    TempData["SearchModel"] = model; 

    return View("Results", results); 
} 

    [HttpGet] 
    public ActionResult Results(int? page) 
    { 
     SearchModel model = (SearchModel)TempData["SearchModel"]; 

     ResultsModel results = new ResultsModel(); 
     results.ResultList = SearchManager.Search(model).ToList(); 

     TempData["SearchModel"] = model; 

     return View("Results", results); 
    } 

對此方法有何想法?似乎需要經過許多才能獲取請求之間傳遞的搜索參數。或者,也許我只是被寵壞了,這一切都發生在WebForms幕後。 :)

+0

Grrr ...這個小問題。TempData顯然仍然使用會話。我不希望用戶不能僅僅因爲他們走了20分鐘和他們的會話過期這種事情不應該需要會話任何想法呢這應該是非常簡單的我認爲我過於複雜 – Scott 2011-05-01 16:19:16

+0

斯科特你可以使用TempData只是爲了填充結果上的隱藏字段這樣會話在進一步的請求中就不起作用了Btw TempData在你使用它初始化視圖後會自動拋棄 – 2011-05-01 16:22:27

+0

隱藏的字段在這裏不起作用我的分頁鏈接只是簡單地將http:// www.site.com/results/2「(對於第2頁),每個分頁鏈接都不是一個表單提交按鈕,所以這些隱藏的字段將永遠不會被髮送回來,這看起來像是一個簡單的問題,也許我正在接近這是錯誤的方式。即使沒有考慮到我的方法,我也會很樂意聽到其他人如何解決這個問題。 – Scott 2011-05-01 16:27:12

8

您的SearchModel類需要包含您的搜索條件和結果。像下面的東西。如果您爲結果使用PagedList,那麼它將包含當前頁面,總頁數,總項目等。您可以通過編寫包含值的搜索條件來限制頁面中的信息量。

public class SearchModel 
{ 
    public string Product { get; set; } 
    public string Sku { get; set; } 
    public string Size { get; set; } 
    public string Manufacturer { get; set; } 
    // etc... 

    public PagedList ResultsList { get; set; } 
} 


[HttpPost] 
public ActionResult Results(SearchModel model) 
{ 
    model.ResultList = SearchManager.Search(model).ToList(); 
    return View(model); 
} 
+0

這是一個有趣的方法。我會明天(或者第二天)嘗試一下,然後再回來。 – Scott 2011-05-03 05:45:52

相關問題