2011-05-16 76 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