我对查看模型比较陌生,并且在使用它们时遇到了一些问题。有一种情况我想知道最好的实践是什么.
我将视图所需的所有信息放入视图模型中。这里有一个例子--请原谅任何错误,这是我想不到的。
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)
但是动态会在表达式中引起问题。
发布于 2011-03-15 10:44:29
经过反复尝试(又称编写代码,然后讨厌它),我目前首选的方法是:
我只使用view-model来绑定输入字段。因此,在您的示例中,如果视图仅编辑两个字段,则view-model将只有两个属性。对于填充视图所需的数据(下拉列表、标签等),我使用动态ViewBag。
我认为显示视图(即填充视图需要显示的任何内容)和捕获发布的表单值(绑定、验证等)是两个独立的关注点。我发现,将填充视图所需的数据与从视图回发的数据混合在一起会变得杂乱无章,并且经常准确地创建您的情况。我不喜欢传递部分填充的对象。
不过,我不确定Automapper (用于将域对象映射到动态ViewBag)的效果如何,因为我还没有使用过它。我相信它有一个可能工作的DynamicMap方法?将发布的强类型ViewModel自动映射到域对象上应该不会有任何问题。
发布于 2011-03-15 10:02:01
如果我理解正确的话,您的视图模型可能与您的域实体非常相似。您提到视图模型返回时大部分是空的,因为只有某些字段是可编辑的。
假设您有一个视图,其中只有几个字段可供编辑(或显示),则这些字段是您应该在视图模型中提供的唯一字段。我通常为每个视图创建一个视图模型,并让控制器或服务处理用户的输入,并在执行一些验证后将其映射回领域实体。
Here是一个关于视图模型的最佳实践的帖子,你可能会发现它很有用。
编辑:您还可以在编辑/POST操作中接受与编辑/获取操作不同的视图模型。我相信只要模型绑定器能弄清楚这一点,这就应该行得通。
https://stackoverflow.com/questions/5306655
复制相似问题