C# ASP.NET MVC中的视图模型和域模型

C# ASP.NET MVC中的视图模型和域模型,c#,asp.net-mvc,C#,Asp.net Mvc,我正在开发一个ASP.NETMVC应用程序,我遇到了一个非常尴尬的局面 我有一个页面,用户可以根据某些条件搜索某些项目(比如,学生)。我曾经将一组学生传递给我的视图,但后来我添加了一些搜索设置,因此我决定创建ViewModel,如下所示 public class SearchViewModel { public string SearchString { get; set; } public bool IsCaseSensitive { get; set; } ...

我正在开发一个ASP.NETMVC应用程序,我遇到了一个非常尴尬的局面

我有一个页面,用户可以根据某些条件搜索某些项目(比如,学生)。我曾经将一组学生传递给我的视图,但后来我添加了一些搜索设置,因此我决定创建ViewModel,如下所示

public class SearchViewModel
{
    public string SearchString { get; set; }
    public bool IsCaseSensitive { get; set; }
    ...
    //other parameters
    ...
    public IEnumerable<Student> Students { get; set; }
}
  • 一般来说,正如我所理解的,ViewModel应该只包含原语及其集合(可能还有第一个问题中的其他ViewModel)。对吗


  • 我不假装这是不可侵犯的事实。但在我看来:

  • 通常只为一个视图创建视图模型
  • 在视图中使用域/数据模型通常是(如果它使开发过程更容易/更快/更清晰)。在您的情况下,我不会在ViewModel中使用学生类
  • ViewModel应包含构建视图所需的所有数据(基本体和非基本体)。但是,如果您可以通过在控制器中执行一些操作来使视图模型更容易和更清晰,那么就应该这样做
  • 创建像StudentViewModel这样的“助手”模型是个好主意吗
  • 我相信是的。您的视图由“学生视图”列表组成。Viewmodels的存在只是为了为您的视图提供以最佳方式构造的数据,以便视图中的必要逻辑尽可能少

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

    然而,在某些场景中,我发现在视图中使用实体是可以接受的:当您使用EF和延迟加载时,您可以在显示数据时使用实体来从延迟加载机制中获益。只有显示的数据才会从数据库中加载。然而,由于几乎总是事先知道需要哪些数据,所以通常有更好的数据加载策略。在开发过程中,当发生大量更改时,延迟加载很方便(加载和显示附加数据很快,而且很容易实现,无需更改太多代码),但通常是在性能审查期间首先要解决的问题

  • 我应该把学生财产分成更小的财产吗?一般来说,正如我所理解的,ViewModel应该只包含原语及其集合(可能还包括第一个问题中提到的其他ViewModel)。对吗
  • 我不同意。您将域设计为表示业务对象,为什么要在viewmodels中再次丢弃它?始终考虑未来的可能性,您的领域模型将需要扩展额外的属性和你今天可以做什么,以降低成本的变化。如果要将域层与表示层分离,请引入包含相同对象的DTO层。在这些对象上,可以应用数据注释和其他仅适用于表示层的内容。使用AutoMapper可以快速地从域对象填充DTO。但是,请注意不要在这些DTO上/使用这些DTO编写业务逻辑


    这是我的2美分

    谢谢。我唯一没有完全理解的是你的第三个答案。关于你的第二个答案,我不应该在我的视图中使用任何域模型(通常是Student,而不是StudentViewModel)。然而,你说我应该用我的学生课。最好的方法是1)保持域模型的学生状态,2)使用StudentViewModel来满足视图的需要,而不是将其划分为不同的属性,这是对的吗?另外,我对DTO条款不太满意。我的ViewModels可以被视为DTO吗?
    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; }
    }
    
    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; }
    }
    
    public class StudentViewModel
    {
        public string Name { get; set; }
        public int GroupId { get; set; }
        public int someData { get; set; }
    }