2011-05-16 74 views
0

繼承人的情景:我有一個用戶對象是這樣的:MVC - 部分在視圖中更新模型

public class User : BaseEntity<User>, IAggregateRoot 
{ 
    public virtual string Name { get; set; } 
    public virtual string Username { get; set; } 
    public virtual string Password { get; set; } 
    public virtual string SecretQuestion { get; set; } 
    public virtual string SecretAnswer { get; set; } 
    public virtual DateTime LastLogin { get; set; } 
} 

在此對象的編輯,我將其加載到的觀點,但我只是想更新一些屬性(即我不想更新LastLogin屬性)。在這種情況下,我會怎麼做?

是創建用戶視圖模型的最佳策略,並且當我嘗試用空的LastLogin字段更新用戶對象時,nhibernate會處理這個問題嗎?

在此先感謝。

編輯

事情是這樣的:

public class UserViewModel 
{ 
    public string Name {get;set;} 
    public string UserName {get;set;} 
    public string Password {get;set;} 
    public string SecretQuestion {get;set;} 
    public string SecretAnswer {get;set;} 
} 

然後編輯:

public ActionResult Edit(int id) 
{ 
    return View(_userRepository.FindById(id)); 
} 

[HttpPost] 
public ActionResult Edit(int id, UserViewModel userViewModel) 
{ 
    try 
    { 

    //Not sure how to update the model 
    //with the view Model and save. 

    _userRepository.Update(????); 
    return RedirectToAction("Index"); 
    } 
    catch 
    { 
    return View(); 
    } 
} 

回答

8

一個好的方法是創建一個UserViewModel,只有要顯示的屬性/更新。不要讓nHibernate知道視圖模型。然後,當編輯回發給您的控制器時,您將從nHibernate中檢索實際的User對象,從視圖模型更新其屬性,然後將其保存回數據庫。

更新

事情是這樣的:

[HttpPost] 
public ActionResult Edit(int id, UserViewModel userViewModel) 
{ 
    try 
    { 
    User model = _userRepository.FindById(id); 

    model.Name = userViewModel.Name; 
    model.Username = userViewModel.Username; 
    model.Password = userViewModel.Password; 
    model.SecretQuestion = userViewModel.SecretQuestion; 
    model.SecretAnswer = userViewModel.SecretAnswer; 

    _userRepository.Update(model); 
    return RedirectToAction("Index"); 
    } 
    catch 
    { 
    return View(); 
    } 
} 

在一個項目中,我一直工作在最近我創建了一個ViewModelBase類包括從一個域模型映射屬性視圖的方法模型,並根據匹配的屬性名稱和類型再回來。我所有的視圖模型都來自ViewModelBase。

還有其他的工具,如AutoMapper,做這種事情和更多,更多。

+0

嗨安德魯謝謝你的回覆。你可以作爲視圖模型的例子和上面使用我的類的編輯帖子嗎?它的編輯位我不確定。 – gdp 2011-05-17 21:48:21

3

我加入另一個答案,因爲還有另一個完全不同的研究方法。

您可以在視圖中使用User對象,然後使用TryUpdateModel指定要在模型中更新的屬性。在這種情況下,您不一定需要視圖模型。如果你願意,你可以使用一個,但是你不需要。然後

POST操作看起來是這樣的:

[HttpPost] 
public ActionResult Edit(int id) 
{ 
    try 
    { 
    User model = _userRepository.FindById(id); 
    var propertiesToUpdate = new string[] { "Name", 
              "Username", 
              "Password", 
              "SecretQuestion", 
              "SecretAnswer" }; 

    if (TryUpdateModel(model, propertiesToUpdate)) { 
     _userRepository.Update(model); 
     return RedirectToAction("Index"); 
    } 
    } 
    catch 
    { 
    // Handle exceptions however you want. 
    } 
    return View(); 
} 

字符串數組是性能模型更新的白名單,和控制器嘗試更新從表單POST數據值(和其他來源)。由於LastLogin不在字符串數組中,因此在更新模型時不會觸及它。

+0

偉大的東西感謝您的意見! – gdp 2011-05-18 18:17:38

+0

嗨安德魯,我得到了兩個工作正常。只是好奇你會喜歡哪種方法,爲什麼? – gdp 2011-05-19 23:19:52

+0

對於具有簡單域模型的應用程序,我可能會選擇這個答案中的方法,因爲創建一堆新的視圖模型類和相關的映射邏輯只是矯枉過正。當領域模型更復雜,並且您的視圖從多個領域對象類中拉取值時,我會使用ViewModel解決方案。在我最近剛開始工作的系統中,我沒有使用ViewModels,但很快就變得太複雜了,無法完全管理。我最終爲大多數視圖實現了ViewModel,導致了更多的類,但更具可讀性的代碼。 – 2011-05-19 23:43:20

0

我的工作,我創建DefaultModelBinder的定製衍生物的技術。它有點像@AndrewCooper發佈的白名單方法一樣工作,但有一點變化。

在我的方法,我堅持一個大鳴喇叭視圖模型,可以有試圖更新它無數的部分景色。在我的情況下,白名單是關鍵的對象標識字段需要通知ViewModel它是如何從存儲庫自動加載自己的 - 因此,期望Partial視圖只包含他們關心的字段,並且,足夠的隱藏字段充實對象身份如果它不立即從路線或任何其他顯而易見的。因此,在POST「模型綁定」階段,首先綁定標識字段(因此觸發'load'以立即從DB中添加模型),並且隨着綁定過程的其餘部分完成,您將擁有有效地將從數據庫中提取的對象與用戶提交的數據「合併」......並且最重要的是(假設你堅持使用MVC約定),現在它已經通過了驗證。

這讓我堅持使用教科書簡單的控制器的方法..像..

Public Function Edit(id As Integer, workOrder as MergedWorkOrderModel) As ActionResult 
    If ModelState.IsValid Then 
     /* save model, send success messaging into ViewBag, etc */ 
     workOrder.Save("ServiceUrl") 
     workOrder.Load("ServiceUrl") 
     ViewBag.SuccessMessage = String.Format("Order {0} saved successfully!", workOrder.Id) 
     Return View(workOrder) 
    Else 
     /* return user model to fix errors */ 
     ViewBag.ErrorMessage = String.Format("Order {0} did not save.", workOrder.Id) 
     Return View(workOrder) 
    End If 
    End Function 

從理論上講,我可以指出我的所有不同的看法回到這個同樣的方法 - 因爲它關心而不是在用戶數據來自......它全部與數據庫中的最新數據合併,驗證並保存完全一樣。

More info at my StackOverflow post