2012-10-02 88 views
0

在MVC應用程序中,我有一些DropDownLists。在我的控制器中,我創建了IEnumerable<SelectListItem>,並將它們轉移到我的視圖中。不幸的是,如果有驗證錯誤,我需要重新創建這些列表,否則視圖渲染失敗。SelectListItem列表應該去哪裏?

在控制器的操作方法我做:

var possibilities = _repo.Objects.Select(o=>new SelectListItem(...)); 
viewmodel.Possibilities = possibilities; 
return View(viewmodel); 

視圖模型具有像這樣定義的可能性屬性:

IEnumerable<SelectListItem> Possibilities { get; set; } 

在我看來,我訪問:

@Html.DropDownListFor(vm=>vm.ThePossibility, vm.Possibilities) 

問題是,當調用表單post操作方法時,視圖模型傳遞給它有一個空的Possibilities,所以當我打電話時:

if(!ModelState.IsValid) 
    return View(model); 

該視圖不會呈現。

我明白爲什麼後操作方法中的propery爲null,但糾正此問題的最佳方法是什麼?我寧願不重新初始化那些列表。

謝謝。

回答

1

如果您不想重新初始化列表,您必須將它們緩存在某個地方,例如會話或其他地方。

坦率地說,在大多數情況下,重建它們會更簡單。您將不得不每次重新分配它們。

+0

是的,這是有道理的,我應該想到這一點。爲了自動發生這種情況,我需要返回一些視圖狀態。謝謝。 – zmbq

1

你應該看看使用Post-Redirect-Get pattern;在this blog post中描述了一對非常好的屬性,這使得在ASP.Net MVC中這非常容易。

+0

如果您在博客文章中提到#13,那麼這裏不適用。它是在談論ModelState,它不包括下拉SelectList。此外,當用戶刷新頁面TempData時,我遇到了TempData方法的大問題,您的ModelState也一樣。對於一條消息來說很好,但對於任何你所需要的實際狀態來說都沒有。 –

+0

@Mystere - 正確 - 模型狀態是持久的,但重定向回到「獲取」請求意味着最初填充下拉列表選項的方法可以重新執行。就頁面重新加載失去模型狀態而言,這是我(我相信大多數人)期望的行爲。 –

1

我通常緩存這些地方或提供一個靜態類獲取通用列表。然後,您可以使用getter在模型中提供對這些模型的訪問權限。

例如:

IEnumerable<SelectListItem> _possibilities 
IEnumerable<SelectListItem> Possibilities 
{ 
    get 
    { 
     if (_possibilities == null) 
      _possibilities = CommonLists.Possibilities(); 

     return possibilities; 
    } 
} 
0

Accessors和JSON(NetwonSoft)是你的朋友。

簡而言之

  1. 當你set模型的IEnumerable<SelectListItem>財產,序列化到公共字符串屬性。
  2. 當你的公共字符串屬性被set,並沒有定義IEnumerable<SelectListItem>(例如空),反序列化字符串屬性到模型的IEnumerable<SelectListItem>財產。
  3. 在您的視圖中,嵌入序列化的字符串,以便在發佈到服務器的帖子之間持久化。 (例如。@Html.HiddenFor(...)

型號

public class MyViewModel 
{ 
    public IEnumerable<SelectListItem> Selections 
    { 
     get 
     { 
      return selections; 
     } 
     set 
     { 
      selections= value; 
      // serialize SelectListItems to a json string 
      SerializedSelections = Newtonsoft.Json.JsonConvert.SerializeObject(value); 
     } 
    } 
    IEnumerable<SelectListItem> selections; 

    public string SerializedSelections 
    { 
     get 
     { 
      return serializedSelections; 
     } 
     set 
     { 
      serializedSelections = value; 
      if(Selections == null) 
      { 
       // SelectListItems aren't defined. Deserialize the string to the list 
       Selections = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<SelectListItem>>(value); 
      } 
     } 
    } 
    string serializedSelections; 
} 

Razor視圖

<form> 
... 
@Html.HiddenFor(m => m.SerializedSelections) 
... 
@Html.DropDownListFor(m => m.SomeProperty, Model.Selections) 
</form>