2010-01-17 72 views
13

通过选择MVC开发我们的新网站,我发现自己处于围绕着我开发的“最佳实践”中,并且显然是实时的。两周前,NerdDinner是我的向导,但随着MVC 2的发展,即使它看起来已经过时了。这是一个令人兴奋的体验,我很荣幸能够每天与智能程序员保持密切联系。有关视图模型和模型更新的最佳实践与子领域

现在我已经偶然发现了一个问题,我似乎无法得到直接的答案 - 无论如何从所有博客 - 我想从社区获得一些见解。这是关于编辑(阅读:编辑动作)。大部分材料,教程和博客都涉及创建和查看模型。因此,虽然这个问题可能不会提出一个问题,但我希望能够进行一些讨论,为我决定我将采取的发展道路做出贡献。

我的模型代表一个用户,有几个字段,如姓名,地址和电子邮件。所有的名字,实际上都是名字,姓氏和中间名。 “详细信息”视图显示所有这些字段,但您一次只能更改一组字段,例如您的姓名。用户扩展一个表单,而其他字段在上面和下面仍然可见。因此,返回的表单包含表示模型的字段的子集。

虽然这对我们和我们的布局来说很有吸引力,但出于各种原因,它会被严重的MVC开发人员所忽视。我一直在阅读一些模式和最佳实践,看起来这不是关于viewmodel == view的范例。还是我错了?

无论如何,NerdDinner支配使用FormCollection和UpdateModel。所有的空字段被愉快地忽略。从那以后,MVC社区放弃了这种方法,以至于没有发现MVC 2中的bug。如果没有您的表单收集中的完整模型,UpdateModel不起作用。

view model pattern接收最赞的似乎是包含自定义视图模型实体,是我的设计问题可以进行兼容只有一个专用视图模型。它需要一个单调乏味的映射,尽管使用Jimmy Bogard的AutoMapperideas可以减轻这种影响,但这可能有价值,也可能不值得。他还提出了视图与视图模型之间的1:1关系。

为了与这些设计范例保持一致,我将为每个扩展字段集创建视图和相关视图。视图模型将各自几乎相同,仅在只读字段中不同,视图也包含很多重复标记。这对我来说似乎是荒谬的。将来,我可能希望能够同时显示两个,更多或全部字段集。

我会专心阅读我希望引发的讨论。提前谢谢了。

+0

“细节视图显示所有这些字段,但您一次只能更改一组字段,例如您的姓名。 “为什么?为什么这会比让用户一次调整整个表单更友好?” – jfar 2010-01-17 20:54:01

+1

你说得对,我会换个话题,它不那么混乱,而且更紧凑,你可以有多个地址,添加,删除,但我们仍然 – Martin 2010-01-17 22:47:46

+0

你已经很好地解释了你的问题了,我一直有同样的问题,并且已经转向了由Jimmy Bogard描述的1:1 View:ViewModel模式,我仍然面临的主要问题是映射ViewModels中有多个域模型 – WDuffy 2010-05-30 20:05:14

回答

0

我有完全相同的问题,但我不能很好地阐明它。

在我的情况下,会有大量的ViewModel,因为不同的用户会根据一组角色看到不同的表单。我认为ViewModel和View之间的1:1关系非常模糊。如果我写一个非常简单地使用EditorForModel而不是更多的超级视图呢?现在我有一个尽管高度退化的视图,所以我也只有一个ViewModel?

我的想法是编写一个EditorForModel,该函数不仅基于反射(即编译时已知的信息),而且还用于(特定于域)运行时规则,例如由当前用户的角色,当前时间等因此,还需要编写自定义的ModelBinder验证以及从Model到ViewModel的自定义映射。尽管如此,这使我无法编写愚蠢的代码,从而导致错误发生。

由于我的Model(或DomainModel)包含很多逻辑,所以我不希望它通过ModelBinding进行修改。而且,由于不可能知道编译时会出现什么字段,因此提供适当的ViewModel是不可能的。然而,“完整的”,即最大的ViewModel是已知的。从ViewModel到Model的映射又涉及到自定义代码,但只要规则可以形式化,就可以实现。

对不起,我的文字很混乱,但我现在自己很困惑,加上我必须跑。像C.T.一样,也不能评论。

+0

使用ValueInjecter http://valueinjecter.codeplex.com/并将FormCollection(或请求)映射到您的实体(它会自动完成),有一个示例asp.net mvc应用程序下载说明了这个 – Omu 2010-06-11 06:56:22

2

最近在验证模型的问题上出现了一些帖子,导致Brad Wilson“Input Validation vs. Model Validation in ASP.NET MVC”的这篇文章。

最初的问题是如何处理ASP.NET MVC验证发布的模型,以及如果有模型的元素,你不想编辑,并没有提供在视图中的字段,但你的控制器正在使用整个模型,可能有人可以使用其他字段为您的控制器制作POST。

因此,使用视图特定模型可以确保只编辑要编辑的字段。

0

看看这个。这是去与ASP.NET MVC 2

 public void Update(MyModel model) 
     { 
      var myModelObject = MyRepository.GetInstance(model.Id); 
      if(myModelObject != null) 
      { 
       ModelCopier.CopyModel(model, myModelObject); 
      } 
      MyRepository.Save(myModelObject); 
     } 

ModelCopier.CopyModel(从OBJ,OBJ到)的方法是在最新MvcFutures一个新的功能。此外,一定要检查出的可扩展模型绑定在MVC期货2

+0

我会的,谢谢 – Martin 2010-04-08 22:07:18

+0

这不是真的使用视图模型,但它是什么?只是似乎是一个实际实体的临时副本? – UpTheCreek 2010-10-08 11:06:54

3

我做它像这样(的映射完成自动内部模型构建器与ValueInjecter):

我有一个示例ASP .NET的MVC应用程序,我证明MVC这样做的最佳实践,你可以看到它在download of the valueinjecter

public ActionResult Edit(long id) 
{ 
     return View(modelBuilder.BuildModel(personService.Get(id))); 
} 

[HttpPost] 
public ActionResult Edit(PersonViewModel model) 
{ 
    if (!ModelState.IsValid) 
     return View(modelBuilder.RebuildModel(model));  
     personService.Save(modelBuilder.BuildEntity(model)); 
     return RedirectToAction("Index"); 
} 

ValueInjecter的快速演示:

//build viewmodel 
    personViewModel.InjectFrom(person) 
        .InjectFrom<CountryToLookup>(person); 

//build entity 
    person.InjectFrom(personViewModel) 
      .InjectFrom<LookupToCountry>(personViewModel); 
+0

什么是你会说Bogards AutoMapper的主要区别吗? – Martin 2010-06-11 12:30:06

+0

@Martin与Automapper你必须为每个可能的对象到对象映射创建映射,并显示如何映射每个属性的部分内容(如果它们不是相同的名称),并且必须设置忽略如果你不'不需要它们,现在使用ValueInjecter你不必做所有这些事情,而且使用ValueInjecter你可以做扁平化和解压(从一种类型到另一种类型,使用你的设置值的算法),有很多例子下载 – Omu 2010-06-11 12:37:51