ViewModel最终成为Model的副本 - 哪里有好处?

时间:2013-12-29 17:55:59

标签: c# asp.net-mvc asp.net-mvc-4 viewmodel

我在这里提出的另一个问题为我打开了一堆蠕虫。目前我开发了我的MVC应用程序,模型代表我的数据,并使用脚手架从这些模型生成我的ViewControllers。如果模型没有所需的信息,我使用部分视图来显示相关信息。经过一番阅读后,我现在理解ViewModel是更好的做事方式。所以我的理解是,对于每个视图,我将有一个特定的ViewModel,它返回该视图的数据。

我有两个模型,一个代表一个项目,另一个,项目选项可能有多个。

public class Item
{
    public int ItemId { get; set; }
    public bool Active { get; set; }
    public string ItemCode { get; set; }
    public string Name { get; set; }
    public List<ItemOption> ItemOptions { get; set; }
    //...
}

public class ItemOption
{
    public int ItemOptionId { get; set; }
    public string Name { get; set; }
    public string Barcode { get; set; }
    //...
}

因此我假设我的ItemDetailViewModel将只包含我在视图中向用户显示的信息:

public class ItemDetailViewModel
{
    public bool Active { get; set; }
    public string ItemCode { get; set; }
    public string Name { get; set; }
    public List<ItemOption> ItemOptions { get; set; }
}

我应该在ItemDetailViewModel上创建自己的ItemOptions列表吗?例如,应该是:

public List<ItemOptionsViewModel> ItemOptions { get; set; }

我想我错过了ViewModel的好处。我已经读过,因此我们可以将一个类中的所有数据都与该视图相关,因此我们可以保持视图的强类型。但是我似乎只是将我的模型复制到我的ViewModel中,所以并没有真正获得任何好处。

此外,我的研究让我想到AutoMapper是最好的前进方式。我是否正确说我只是将以下内容放入我的启动配置中:

Mapper.CreateMap<Item, ItemDetailViewModel>()
            .ForMember(x => x.Active, o => o.MapFrom(s => s.Active))
            .ForMember(x => x.ItemCode, o => o.MapFrom(s => s.ItemCode))
            .ForMember(x => x.Name, o => o.MapFrom(s => s.Name));
            .ForMember(x => x.ItemOptions, o => o.MapFrom(s => s.ItemOptions));

如果我这样做,它如何适用于编辑视图。如果我将它们保存回ItemDetailViewModel,它会在EF中更新我的数据库吗?

1 个答案:

答案 0 :(得分:7)

当有好处时使用视图模型。如果您的域模型已经具有完全相同的属性和验证规则以及与您的视图模型相对应的此特定视图的错误消息,那么很明显您可以重用域模型而不需要声明视图模型。但根据我的经验,这种情况很少发生。或者如果是这种情况,那么您可能会开始问自己为什么您的域模型如此耦合到视图。我的意思是特定于视图的错误消息不应该是域模型的一部分。

所以你应该一如既往地找到合适的平衡点。通常有一个主视图模型聚合(作为属性)一个或多个域模型。

作为AutoMapper配置中的旁注,如果每个属性具有相同的名称,则无需映射它们。这就是为什么框架被称为AutoMapper,因为它按惯例工作。您问题中显示的所有长映射代码都等同于更简单的Mapper.CreateMap<Item, ItemDetailViewModel>();