将实体(表单)传递给控制器​​操作的正确方法

时间:2012-09-05 10:47:15

标签: asp.net-mvc-3 controller action

我正在编写一个创建新用户的控制器操作。目前,控制器操作将 用户实体模型 作为参数。

我想知道是否应该在自己的 视图模型 中传递前端的值,然后提取值并在后端创建实体?

public ActionResult AddUser(User user)
{
  context.Users.Add(user);
  context.SaveChanges();
}

VS

public ActionResult AddUser(UserViewModel userViewModel)
{
  var user = new User(userViewModel.Name);
  context.User.Add(user);
  context.SaveChanges();
}

谢谢!

2 个答案:

答案 0 :(得分:1)

学术方法是创建一个额外的viewmodel类,它只公开您需要显示的数据或用户输入信息所需的字段,并将它们映射到您的域模型,如第二个示例所示。

但对于小型应用或当您需要模型中的所有字段时,我认为将域模型对象传递给视图绝对可以。

另一个需要考虑的重要事项是安全性/验证。使用隐式mvc映射机制和完整域模型时,错误的用户可能会向您的控制器发送不希望存储在数据库中的值。 使用单独的视图模型类涉及显式映射步骤,您必须明确告知系统viewmodel(=用户输入的数据)中哪个字段要映射到域模型。

答案 1 :(得分:1)

与大多数事情一样,有多种方法可以做到这一点。最终在这种情况下,它通常归结为个人偏好。

当我做同样的事情时,我经常会问自己,传入方法的内容实际上是否真的是有效的User。我喜欢让我的模型保持内部防止无效状态,而不是依赖调用代码来保持模型的有效性。

因此,有时会有一些操作接收描述模型但不完全构建模型的信息。在这些情况下,我更喜欢使用视图模型。如果没有其他原因而不是一致性,这通常会导致我全面使用视图模型。

如果我需要页面上多个模型的信息,它会派上用场。拥有一个视图模型,它是我需要的信息的复合,而不是像Tuple两个模型的东西,对我来说感觉更清洁。这也允许我向视图模型(计算字段,标志等)添加其他属性,这些属性对视图有用但会污染业务对象。 (切换到显示/隐藏某些表单元素,验证项等)。

通常,您可以通过注意对象User)和数据结构({之间的区别来找到您对此类问题的偏好。 {1}})。在传统的面向对象意义上,UserViewModel应隐藏其数据成员并提供功能接口,而像User这样的平面数据结构将公开其数据成员并且没有任何有意义的功能。

由于视图只是想要绑定到数据成员,我通常使用平面视图模型而不是域对象。