繁体   English   中英

ASP.NET MVC中的ViewModel和域模型

[英]ViewModels and domain models in 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)组成。 这是正确的吗?

我不假装这个不可侵犯的事实。 但我认为:

  1. 通常,视图模型仅针对一个视图创建。
  2. 通常在视图中使用域/数据模型(如果它使开发过程更容易/更快/更清晰)。 在您的情况下,将不会在ViewModel中使用Student类。
  3. ViewModel应该包含构建视图所需的所有数据(原始而非原始)。 但是,如果您可以通过在控制器中进行一些工作来使视图模型更轻松,更清晰,那么应该做到这一点。
  1. 创建诸如StudentViewModel之类的“帮助器”模型是一个好主意吗?

我相信是。 您的视图“包含”“学生视图”列表。 视图模型仅用于以最佳方式构造的数据为您的视图提供服务,以使视图中的必要逻辑尽可能少。

  1. 据我了解,ViewModel绝不应该包含域模型。

我建议不要在视图中使用您的实体,尤其是在处理表单或其他数据输入方式时。 在这种情况下,创建一个仅包含您希望用户提交的属性的特殊“表单模型”通常很有趣。 这也使您可以为此特定形式编写验证逻辑。 可以将其视为为您的表单提供服务的模型,类似于视图模型为您的视图提供服务的方式。 使用AutoMapper填写这些表单模型可以使您的生活更轻松。

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

  1. 我应该将学生财产分为较小的财产吗? 一般而言,据我所知,ViewModel应该仅由基元及其集合(以及第一个问题中的其他ViewModel)组成。 这是正确的吗?

我不同意。 您设计了域来表示您的业务对象,为什么还要在视图模型中再次丢弃它呢? 始终考虑将来可能需要使用其他属性扩展域模型的可能性,以及您今天可以采取的措施以减少此类更改的成本。 如果要将域层与表示层分开,请引入一个包含相同对象的DTO层。 在这些对象上,您可以应用数据注释和仅适用于表示层的其他内容。 可以使用AutoMapper快速完成从域对象填充DTO。 但是,请注意不要在这些DTO上/与这些DTO一起编写业务逻辑。

这是我的2美分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM