【问题标题】:ASP.NET MVC view model best practicesASP.NET MVC 视图模型最佳实践
【发布时间】:2011-09-16 16:16:20
【问题描述】:

我的 ASP.NET MVC 站点连接到 WCF 服务以获取数据。 WCF 服务返回如下数据协定:

[DataContract]
public class Person
{
    [DataMember]
    public string First { get; set; }

    [DataMember]
    public string Last { get; set; }
}

我的 MVC 项目中的视图模型如下所示:

public class MyViewModel
{
    public string SomeExtraField1 { get; set; }
    public string SomeExtraField2 { get; set; }
    public string SomeExtraField3 { get; set; }

    public Person Person { set; set; }
}

我的视图模型是否应该引用从数据服务返回的“Person”数据协定?或者我应该在我的 MVC 项目中创建一个新的“Person”类来反映“Person”数据协定上的属性?

WCF 服务调用隐藏在接口后面。似乎让接口引用数据合同使我的接口成为一个泄漏的抽象。但是,我有一些人认为在我的 MVC 项目中创建一个额外的“Person”类来反映数据契约是代码膨胀。

围绕这种分层/解耦的最佳做法是什么?

【问题讨论】:

    标签: asp.net-mvc viewmodel


    【解决方案1】:

    我的视图模型是否应该引用从数据服务返回的“Person”数据协定?

    不,避免这种情况,它会给开发人员一种他们正在使用视图模型的错误印象。在进行代码审查时,我经常会看到这样的代码:

    public class MyViewModel
    {
        public SomeDomainModel1 Model1 { get; set; }
        public SomeDomainModel2 Model2 { get; set; }
        ...
    }
    

    这是错误的。当我批评他们不使用视图模型时,他们向我展示了这一点并告诉我:“Darin,看,我正在使用视图模型”,不幸的是,这不是视图模型应该如何工作的。它们不是域模型的包装器。

    或者我应该在我的 MVC 项目中创建一个新的“Person”类来反映“Person”数据协定上的属性?

    是的,您可以创建一个PersonViewModel 并只包含您的视图当然需要的属性。

    或者,如果您正在为其设计此视图模型的特定视图只需要一些属性,您也可以使其看起来像这样:

    public class MyViewModel
    {
        public string SomeExtraField1 { get; set; }
        public string SomeExtraField2 { get; set; }
        public string SomeExtraField3 { get; set; }
    
        // this would be for example the concatenation of your domain model 
        // first name and last name as that's what this particular view needs to 
        // display
        public string PersonFullName { set; set; }
    }
    

    就你的领域模型和视图模型之间的转换而言,AutoMapper 简单地说就是:优秀。

    【讨论】:

    • 是否可以通过构造函数将域对象传递给视图模型并私下使用他的域对象?
    • @Fixer,不,默认模型绑定器会阻塞。
    • @Darin,+1 介绍 AutoMapper
    • 如果域模型只有视图需要的东西,没有额外的东西怎么办?那会有什么缺点呢?
    • @kbmax,我还没有遇到过这种情况。视图总是有一些特定的要求,无论是用于显示、编辑还是验证目的。但是,当然,如果您认为视图模型不会为您的场景带来任何额外的好处,请绝对不要使用它们。
    【解决方案2】:

    我会说创建一个映射器层,它将在 WCF Person 类和“镜像”Person 类之间进行转换。这样,您将 MVC 实现绑定到 POCO,而不是直接绑定到 WCF。这增加了将 WCF 替换为另一个服务的能力,而无需在未来需要时触及 MyViewModel(更松散的耦合)。

    【讨论】:

      猜你喜欢
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多