ASP.NET MVC中的ViewModels和域模型

时间:2014-11-23 19:11:11

标签: c# asp.net-mvc

我正在开发一个ASP.NET MVC应用程序,我遇到了一个非常尴尬的情况。

我有一个页面,用户可以通过某些标准搜索某些项目(比如学生)。我曾经将一组学生传递给我的视图,但后来我添加了一些设置进行搜索,所以我决定按如下方式创建ViewModel

public class SearchViewModel
{
    public string SearchString { get; set; }
    public bool IsCaseSensitive { get; set; }
    ...
    //other parameters
    ...
    public IEnumerable<Student> Students { get; set; }
}

然后我想到了当我必须向每个学生添加一些额外信息时的情况,这些信息没有存储在数据库中并且是在控制器上生成的。我的第一个想法是非常愚蠢 - 我添加了一个额外的数组来保存在ViewModel中,如下所示:

public class SearchViewModel
{
    public string SearchString { get; set; }
    public bool IsCaseSensitive { get; set; }
    ...
    //other parameters
    ...
    public IEnumerable<Student> Students { get; set; }
    public IEnumerable<int> someData { get; set; }
}

为了获取数据,客户端代码必须让学生在数组中定位,然后转到someData数组中的相应位置。

我不太喜欢这个想法所以我把我的模型改为包含搜索参数+另外一个模型来保存学生对象及其数据。

public class SearchViewModel
{
    public string SearchString { get; set; }
    public bool IsCaseSensitive { get; set; }
    ...
    //other parameters
    ...
    public IEnumerable<StudentViewModel> StudentModels { get; set; }
}

public class StudentViewModel
{
    public Student Student { get; set; }
    public int someData { get; set; }
}
  1. 创建像StudentViewModel这样的'帮助'模型是一个好主意吗?我可能不会在SearchViewModel内部的任何地方使用StudentViewModel。鉴于SearchViewModel本身就是一种“帮助”模型,创建另一个仅在SearchViewModel内部使用的模型似乎有点奇怪。是这样吗?

  2. 据我所知,ViewModel永远不应包含域模型。我应该将学生财产划分为较小的财产吗?例如,像这样:

    public class StudentViewModel
    {
        public string Name { get; set; }
        public int GroupId { get; set; }
        public int someData { get; set; }
    }
    
  3. 一般来说,正如我所理解的,ViewModel应该包含的基元及其集合(可能还有第一个问题中的其他ViewModel)。这是正确的吗?

2 个答案:

答案 0 :(得分:1)

我不假装这个不可侵犯的真相。但在我看来:

  1. 通常只为一个视图创建视图模型。
  2. 通常在视图中使用域/数据模型(如果它使开发过程更容易/更快/更清晰)。在您的情况下,我不会在ViewModel中使用Student类。
  3. ViewModel应包含构建视图所需的所有数据(基元而非基元)。但是如果你可以通过在控制器中完成一些工作来使视图模型更容易和更清晰,那么应该完成它。

答案 1 :(得分:1)

  1. 创建这样的帮助者是一个好主意吗?模特作为StudentViewModel?
  2. 我相信它是。您的观点包含&#39;一系列学生观点&#39;。 Viewmodels仅用于以最佳方式构建数据来为您的视图提供服务,以便视图中的必要逻辑尽可能小。

    1. 据我所知,ViewModel永远不应包含域模型。
    2. 我建议不要在视图中使用您的实体,尤其是在处理表单或其他数据输入方式时。在这种情况下,创建一个特殊的&#34; Form模型&#34;仅包含您希望用户提交的属性。这也允许您为此特定表单编写验证逻辑。将其视为为您的表单提供服务的模型,类似于视图模型为您的视图提供服务的方式。使用AutoMapper填充这些表单模型,让您的生活更轻松。

      但是,在某些情况下,我发现在视图中使用实体是可以接受的:当您使用EF和延迟加载时,您可以在显示数据时使用实体从延迟加载机制中获利。只显示您显示的数据将从数据库加载。但是,由于事先几乎总是知道您需要哪些数据,因此通常有更好的数据加载策略。在开发过程中发生大量更改时,延迟加载非常方便(加载和显示其他数据快速且易于实现而无需更改大量代码),但通常是性能评估期间首先要解决的问题。

      1. 我应该将学生财产划分为较小的财产吗?一般来说,正如我所理解的,ViewModel应该只包含基元及其集合(可能还有第一个问题中的其他ViewModel)。这是对的吗?
      2. 我不同意。您将域设计为代表业务对象,为什么要在视图模型中再次抛弃它?始终考虑未来可能需要使用额外属性扩展您的域模型,以及您今天可以做些什么来降低此类更改的成本。如果要将域图层与表示层分开,请引入包含相同对象的DTO图层。在这些对象上,您可以应用数据注释和仅适用于表示层的其他内容。使用AutoMapper可以快速完成从域对象填充DTO。但是,请注意不要在/或使用这些DTO编写业务逻辑。

        这是我的2美分。