ASP.NET MVC ViewModel模式

时间:2009-09-01 07:43:36

标签: asp.net asp.net-mvc design-patterns viewmodel

编辑我为使用ViewModels 从视图中填充和读取数据做了一些更好的事情,称之为 ValueInjecter http://valueinjecter.codeplex.com/

它由http://prodinner.codeplex.com使用 - 一个ASP.net MVC示例应用程序  

您可以看到在prodinner中使用ViewModel的最佳方式

使用ViewModel存储映射逻辑并不是一个好主意因为有重复和SRP违规,但现在使用ValueInjecter我有干净的ViewModels和干映射代码

<小时/> 这是旧的东西,不要用它:
我制作了一个ViewModel模式,用于编辑asp.net mvc中的内容 当您必须为表单编辑实体时,此模式非常有用,您必须在表单上放置一些下拉菜单,供用户选择一些值

    public class OrganisationBadViewModel
    {
        //paramterless constructor required, cuz we are gonna get an OrganisationViewModel object from the form in the post save method
        public OrganisationViewModel() : this(new Organisation()) {}
        public OrganisationViewModel(Organisation o)
        {
            Organisation = o;
            Country = new SelectList(LookupFacade.Country.GetAll(), "ID", "Description", CountryKey);  
        }       
        //that's the Type for whom i create the viewmodel
        public Organisation Organisation { get; set; }
...     

    }

4 个答案:

答案 0 :(得分:11)

这看起来非常类似于Wrox Professional ASP.NET MVC一书中的推荐做法,第一章可从上述网址免费获得。

从第100页开始,他们有一个关于 ViewData和ViewModels 的部分。

  

当Controller类决定将HTML响应呈现给客户端时,它负责将呈现响应所需的所有数据显式传递给视图模板。视图模板永远不应该执行任何数据检索或应用程序逻辑 - 而应该将自己限制为仅具有由控制器传递给它的模型/数据驱动的渲染代码。

     

[...]

     

使用[ViewModel“]模式时,我们创建了针对特定视图场景优化的强类型类,并公开了视图模板所需的动态值/内容的属性。然后,我们的控制器类可以填充这些视图优化类并将其传递给我们的视图模板以供使用。这样可以在视图模板中启用类型安全,编译时检查和编辑器智能感知。

取自“第1章”书呆子晚宴“来自Rob Connery等人撰写的专业ASP.NET MVC 1.0,由Wrox出版”。原件位于http://tinyurl.com/aspnetmvc

答案 1 :(得分:9)

有些事情让我烦恼。

  1. 术语。 ViewModel就是这种情况,是一个简单的视图数据,由控制器填充并稍后使用。 View对控制器一无所知,因为ASP.NET MVC基础结构负责选择控制器和适当的操作。控制器处理用户交互。我认为它看起来更像Passive View而不是ViewModel(我假设ViewModel是指Model-View-ViewModel模式)。

  2. 细节。填充视图数据的控制器不应该知道视图如何实现的细节。然而,OrganisationViewModel.Country公开了不必要的细节(SelectListItem是纯视图实现细节)。从而使控制器依赖于视图实现细节。我认为应该改变以避免它。考虑使用一些保存国家数据的对象。

  3. 希望这有帮助。

答案 2 :(得分:1)

一般来说,我觉得它看起来不错,为域对象创建视图模型通常是个好主意。

我没有看过每一行代码,但引起我注意的一件事是OrganisationViewModel的构造函数。我用以下方法重写它:

public OrganisationViewModel() : this(new Organisation()) { }

public OrganisationViewModel(Organisation o)
{
  Organisation = o;
  InitCollections();
}

这会删除一些重复的代码,因为您不必在两个构造函数中调用InitCollections()。当然,这只是一个小细节,与一般的想法无关。

答案 3 :(得分:1)

我们开始这样做,但我们的控制器开始变得怪异(因为我们的ViewModel不一定以1:1的方式映射到我们的数据库)。为了缓解这种情况,我们创建了Mapper类,用于创建ViewModel,然后映射回数据库绑定的数据。然后控制器只调用Mapper类方法。似乎运作良好。