有关视图模型和模型更新的最佳实践以及字段的子集

时间:2010-01-17 20:42:43

标签: asp.net asp.net-mvc asp.net-mvc-2 automapper

通过选择MVC来开发我们的新网站,我发现自己正处于围绕着我的“最佳实践”中实时开发。两周前,NerdDinner是我的向导,但随着MVC 2的发展,即使它看起来已经过时了。这是一次激动人心的经历,我很荣幸能够每天与智能程序员保持密切联系。

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

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

虽然这对我们和我们的布局问题很有吸引力,但由于各种原因,它会被严肃的MVC开发人员所避开。我一直在阅读一些模式和最佳实践,看起来这与viewmodel == view的范例无关。或者我弄错了?

无论如何,NerdDinner指示使用FormCollection och UpdateModel。所有空字段都被高兴地忽略了。从那以后,MVC社区已经放弃了这种方法,以至于没有发现MVC 2中的bug。如果没有表单集中的完整模型,UpdateModel将无法运行。

获得最多赞誉的view model pattern似乎是包含自定义视图模型实体的专用视图模型,并且是我的设计问题唯一可以与之兼容的模型。它需要进行繁琐的绘图,尽管使用AutoMapper和吉米·博加德的ideas可以减轻这种情况,这可能是也可能是不值得的。他还提出了视图和视图模型之间的1:1关系。

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

我会非常认真地阅读我希望引发的讨论。非常感谢提前。

4 个答案:

答案 0 :(得分:3)

我这样做(映射是使用ValueInjecter在modelBuilder中自动完成的):

我有一个示例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);

答案 1 :(得分:2)

最近有一些关于验证模型的帖子,导致Brad Wilson“Input Validation vs. Model Validation in ASP.NET MVC”的这篇文章。

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

因此,使用View特定模型可以确保只能编辑您想要编辑的字段。

答案 2 :(得分:0)

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

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

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

由于我的Model(或DomainModel)包含很多逻辑,我不希望它通过ModelBinding进行修改。此外,由于无法知道编译时将出现哪些字段,因此无法提供适当的ViewModel。然而,'full',即最大ViewModel是已知的。从ViewModel到模型的映射再次涉及自定义代码,但只要规则可以正式化,那就应该有效。

抱歉,我的文字非常令人困惑,但我现在很困惑,加上我要跑。像C.T.一样,也无法评论。

答案 3 :(得分: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 from,obj to)是最新MvcFutures中的新函数。另外一定要查看MVC Futures 2中的Extensible Model Binder。