[英]Using view models in ASP.NET MVC 3
我是相对较新的查看模型的人,在使用模型时遇到了一些问题。 在一种情况下,我想知道最佳实践是什么...
我将视图所需的所有信息都放入视图模型中。 这是一个示例-请原谅任何错误,这已超出我的脑海。
public ActionResult Edit(int id)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
var model = new ProjectEdit();
model.MapFrom(project); // Extension method using AutoMapper.
return View(model);
}
如果屏幕仅允许编辑一个或两个字段,则在视图模型返回时会丢失大量数据(应该如此)。
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
try
{
if (!ModelState.IsValid)
return View(model) // Won't work, view model is incomplete.
model.MapTo(project); // Extension method using AutoMapper.
ProjectService.UpdateProject(project);
// Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
// Add a message for the user to temp data.
return View(model) // Won't work, view model is incomplete.
}
}
我的临时解决方案是从头开始重新创建视图模型,从域模型重新填充它,将表单数据重新应用到它,然后照常进行。 但这使视图模型参数毫无意义。
[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
var project = ProjectService.GetProject(id);
if (project == null)
// Something about not found, possibly a redirect to 404.
// Recreate the view model from scratch.
model = new ProjectEdit();
model.MapFrom(project); // Extension method using AutoMapper.
try
{
TryUpdateModel(model); // Reapply the form data.
if (!ModelState.IsValid)
return View(model) // View model is complete this time.
model.MapTo(project); // Extension method using AutoMapper.
ProjectService.UpdateProject(project);
// Add a message for the user to temp data.
return RedirectToAction("details", new { project.Id });
}
catch (Exception exception)
{
// Add a message for the user to temp data.
return View(model) // View model is complete this time.
}
}
有没有更优雅的方式?
编辑
这两个答案都是正确的,因此,如果可以的话,我会同时给予奖励。 MJ点了点头,但是由于经过反复试验,我发现他的解决方案是最精简的。
我仍然可以使用助手,吉米。 如果我将需要显示的内容添加到视图包(或视图数据)中,就像这样...
ViewBag.Project= project;
然后,我可以执行以下操作...
@Html.LabelFor(model => ((Project)ViewData["Project"]).Name)
@Html.DisplayFor(model => ((Project)ViewData["Project"]).Name)
有点骇人听闻,在某些情况下,它要求使用System.ComponentModel.DisplayNameAttribute
装饰域模型,但我已经做到了。
我想打电话给...
@Html.LabelFor(model => ViewBag.Project.Name)
但是动态会导致表达式出现问题。
经过反复试验(也就是编码,然后讨厌)学习之后,我目前首选的方法是:
我仅使用视图模型来绑定输入字段。 因此,在您的情况下,如果您的视图仅编辑两个字段,那么您的视图模型将只有两个属性。 对于填充视图所需的数据(下拉列表,标签等),我使用动态ViewBag。
我认为显示视图(即填充视图需要显示的任何内容)和捕获发布的表单值(绑定,验证等)是两个单独的问题。 而且我发现,将填充视图所需的数据与从视图中发布回去的数据混在一起会很混乱,并且经常会准确地创建您的情况。 我不喜欢传来的部分填充的对象。
我不确定这如何与Automapper(将域对象映射到动态ViewBag)一起使用,因为我没有使用过。 我相信它可以使用DynamicMap方法吗? 将发布的强类型ViewModel自动映射到Domain对象上应该没有任何问题。
如果我理解正确,则您的视图模型可能看起来与域实体非常相似。 您提到过,由于只有某些字段是可编辑的,因此viewmodel几乎可以返回为空。
假设您有一个视图,其中只有几个字段可用于编辑(或显示),那么这些是您应该在视图模型中提供的唯一字段。 我通常为每个视图创建一个视图模型,并在执行一些验证后让控制器或服务处理用户的输入并将其映射回域实体。
这里是有关可能会有用的视图模型最佳实践的主题。
编辑:您还可以在Edit / POST操作中接受与Edit / GET操作不同的视图模型。 我相信,只要模型联编程序能够弄清楚它,它就应该起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.