发布表单时控制器中的模型绑定 - 为什么使用视图模型而不是域模型中的类?
我对 ASP.NET MVC 3 还比较陌生。我遇到过视图模型及其用于将数据从控制器传递到视图的用途。在我最近的关于模型绑定的问题< /a> 两位专家建议我也应该使用视图模型进行模型绑定。
这是我以前没有遇到过的。但两个人都向我保证这是最好的做法。有人可以阐明视图模型更适合模型绑定的原因吗?
这是一个示例情况:我的域模型中有一个简单的类。
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
}
这是我的控制器:
public class TestController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult ListParents()
{
return View(testParentRepository.TestParents);
}
public ViewResult EditParent(int testParentID)
{
return View(testParentRepository.TestParents.First(tp => tp.TestParentID == testParentID));
}
[HttpPost]
public ActionResult EditParent(TestParent testParent)
{
if (ModelState.IsValid)
{
testParentRepository.SaveTestParent(testParent);
TempData["message"] = string.Format("Changes to test parents have been saved: {0} (ID = {1})",
testParent.Name,
testParent.TestParentID);
return RedirectToAction("ListParents");
}
// something wrong with the data values
return View(testParent);
}
}
因此,在 HTTP POST 到达时调用的第三个操作方法中,我使用 TestParent 进行模型绑定。这感觉非常方便,因为生成 HTTP POST 请求的浏览器页面包含 TestParent 所有属性的输入字段。我实际上认为 Visual Studio 为 CRUD 操作提供的模板也是如此工作的。
然而,我得到的建议是第三个操作方法的签名应为 public ActionResult EditParent(TestParentViewModel viewModel)
。
I'm still reasonably new to ASP.NET MVC 3. I have come across view models and their use for passing data from a controller to the view. In my recent question on model binding two experts suggested that I should use view models for model binding as well.
This is something I haven't come across before. But both guys have assured me that it is best practise. Could someone maybe shed some light on the reasons why view models are more suitable for model binding?
Here is an example situation: I have a simple class in my domain model.
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
}
And this is my controller:
public class TestController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult ListParents()
{
return View(testParentRepository.TestParents);
}
public ViewResult EditParent(int testParentID)
{
return View(testParentRepository.TestParents.First(tp => tp.TestParentID == testParentID));
}
[HttpPost]
public ActionResult EditParent(TestParent testParent)
{
if (ModelState.IsValid)
{
testParentRepository.SaveTestParent(testParent);
TempData["message"] = string.Format("Changes to test parents have been saved: {0} (ID = {1})",
testParent.Name,
testParent.TestParentID);
return RedirectToAction("ListParents");
}
// something wrong with the data values
return View(testParent);
}
}
So in the third action method which gets invoked when an HTTP POST arrives I used TestParent for model binding. This felt quite convenient because the browser page that generates the HTTP POST request contains input fields for all properties of TestParent. And I actually thought that's the way the templates that Visual Studio provides for CRUD operations work as well.
However the recommendation that I got was that the signature of the third action method should read public ActionResult EditParent(TestParentViewModel viewModel)
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
起初听起来很吸引人,但随着您的模型和视图操作变得越来越复杂,您开始看到使用 ViewModel 来处理(大多数)所有事情的价值,尤其是输入场景。
情况 1 - 大多数 Web 框架都容易出现过度发布的情况。如果您直接绑定到域模型,则很可能会过度发布数据并恶意更改不属于用户的内容。我发现绑定到输入视图模型比使用白名单或黑名单的长字符串列表更干净,尽管还有一些其他有趣的方式绑定到接口。
情况 2 - 随着您的输入变得越来越复杂,您有时会遇到需要提交和验证不直接在域模型中的字段(“我同意”复选框等)的情况
情况 3 - 更多的是个人的事情,但我发现模型绑定到关系域对象有时是一个巨大的痛苦。在 AutoMapper 中将它们链接起来比处理复杂对象图的 MVC 模型绑定器更容易。 MVC 的 html 帮助程序在处理原始类型时也比深度关系模型更顺畅。
使用 ViewModel 的缺点是它不是很 DRY。
所以这个故事的寓意是,绑定到领域模型对于简单的事情来说是一个可行的解决方案,但随着复杂性的增加,拥有一个单独的视图模型然后在两者之间进行映射变得更容易。
It sounds appealing at first, but as your models and view actions get increasingly complex, you start to see the value of using ViewModels for (most) everything, especially input scenarios.
Case 1 - Most web frameworks are susceptible to over-posting. If you are binding straight to your domain model, it is very possible to over-post data and maliciously change something not belonging to the user. I find it cleaner to bind to an input view model than have long string lists of white lists or black lists, although there are some other interesting ways with binding to an interface.
Case 2 - As your input grows in complexity, you'll run into times when you need to submit and validate fields not directly in the domain model ('I Agree' checkboxes, etc)
Case 3 - More of a personal thing, but I find model binding to relational domain objects to be a giant pain at times. Easier to link them up in AutoMapper than deal with MVC's modelbinder for complicated object graphs. MVC's html helpers also work more smoothly against primitive types than deep relational models.
The negatives of using ViewModels is that it isn't very DRY.
So the moral of the story is, binding to domain models can be a viable solution for simple things, but as the complexity increases, it becomes easier to have a separate view model and then map between the two.