2011-05-08 188 views
1

視圖模型返回數據我有像這樣的視圖模型:與POST請求

public class MyViewModel 
{ 
    public string Name { get; set; } 
    public List<Purchases> Purchases { get; set; } 
} 

此視圖模型被髮送到的視圖,允許用戶編輯名稱屬性。該採購屬性僅用於創建一個下拉框爲它:

<%: Html.DropDownListFor(t => t.Name, new SelectList(Model.Purchases, "Value", "Text")) %></p> 

這工作得很好。

然而,當我執行服務器端驗證,然後返回查看,我得到一個對象空引用錯誤,因爲購買屬性現在設置爲null。我猜這是因爲當被提交表單,因爲購買房地產沒有被綁定到任何可編輯的控制,它沒有被傳遞迴用視圖模型。

我怎樣才能防止這種情況發生?我希望始終發回要發送的列表以及發佈請求。

回答

1

您不需要發回列表。如果驗證失敗,那麼只需從頭開始重建視圖模型。 MVC的主要賣點之一是它在無狀態環境中的運行情況如何。 Web窗體使用ViewState做這種事情,我不認爲你想要複製這種功能。

我想有此兩個重載操作方法(這兩個名稱相同,但不同的方法簽名)。一個具有[HttpGet()]屬性,另一個具有[HttpPost()]。如果您的模型在POST上被發現無效,那麼只需返回「GET」方法(注意:您需要傳入重建視圖所需的任何參數)。

當我說的回報,我的意思是:

return MyGetAction(); 

重定向到GET操作。

如果模型是有效的,那麼你可以/應該執行RedirectToAction() GET操作(這意味着如果用戶點擊刷新按鈕,它不會再次提交表單,這稱爲Post/Redirect/Get PRG)圖案)

1

你不得不爲每一個在除了選擇列表中的列表中元素的一個隱藏的輸入。話雖如此,我認爲在服務器上緩存查詢結果是處理重新填充列表的更好方法,如果您不想再次執行查詢。如果服務器可以掛在它上面,那麼通過線路發回數據是沒有意義的。就我個人而言,除非它被證明是性能瓶頸,否則我甚至不會爲高速緩存而煩惱。只需從數據庫填充模型選擇列表。

<% for (int i = 0; i < Model.Purchases.Length; ++i) { %> 
    <%: Html.Hidden(string.Format("Purchases[{0}]", i), Model.Purchases[i]) %> 
<% } %> 
1

李耿氏是即期。爲了讓答案更具體一些,在ModelState無效的情況下重新構建非標量值是非常常見的。這可以通過簡單地返回Controller中的[HttpGet]版本來完成。但是,您可以簡單地手動重新生成採購集合。隨你便。

[HttpGet] 
public ActionResult MyView(string name) 
{ 
    //get entity and build up a view model 
    var entity = _myDb.GetEntity(name); 
    MyViewModel vm = AutoMapper.Map<Entity, MyViewModel>(entity); 

    return vm; 
} 

[HttpPost] 
public ActionResult MyView(MyViewModel vm) 
{ 
    If(!ModelState.IsValid) 
    { 
     //here is one way of doing it 
     return MyView(""); 

     //OR 

     vm.Purchases = GetSomePurchasesBro(); 
     return View(vm); 
    } 

    //continue on persisting and doing the Post Redirect Get 
} 

P.S. 調用

return MyView(""); 

可以

return MyView(vm.Name); 

兩者代替會做同樣的事情(只要您使用的HTML輔助擴展,即Html.TextBoxFor(x=>x.Name)

Defaut模型結合看在模型狀態爲呈現Html時的attemptValues。這裏描述的是by Steve Sanderson.