我正在开发一个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; }
}
创建像StudentViewModel这样的'帮助'模型是一个好主意吗?我可能不会在SearchViewModel内部的任何地方使用StudentViewModel。鉴于SearchViewModel本身就是一种“帮助”模型,创建另一个仅在SearchViewModel内部使用的模型似乎有点奇怪。是这样吗?
据我所知,ViewModel永远不应包含域模型。我应该将学生财产划分为较小的财产吗?例如,像这样:
public class StudentViewModel
{
public string Name { get; set; }
public int GroupId { get; set; }
public int someData { get; set; }
}
一般来说,正如我所理解的,ViewModel应该包含仅的基元及其集合(可能还有第一个问题中的其他ViewModel)。这是正确的吗?
答案 0 :(得分:1)
我不假装这个不可侵犯的真相。但在我看来:
答案 1 :(得分:1)
我相信它是。您的观点包含&#39;一系列学生观点&#39;。 Viewmodels仅用于以最佳方式构建数据来为您的视图提供服务,以便视图中的必要逻辑尽可能小。
我建议不要在视图中使用您的实体,尤其是在处理表单或其他数据输入方式时。在这种情况下,创建一个特殊的&#34; Form模型&#34;仅包含您希望用户提交的属性。这也允许您为此特定表单编写验证逻辑。将其视为为您的表单提供服务的模型,类似于视图模型为您的视图提供服务的方式。使用AutoMapper填充这些表单模型,让您的生活更轻松。
但是,在某些情况下,我发现在视图中使用实体是可以接受的:当您使用EF和延迟加载时,您可以在显示数据时使用实体从延迟加载机制中获利。只显示您显示的数据将从数据库加载。但是,由于事先几乎总是知道您需要哪些数据,因此通常有更好的数据加载策略。在开发过程中发生大量更改时,延迟加载非常方便(加载和显示其他数据快速且易于实现而无需更改大量代码),但通常是性能评估期间首先要解决的问题。
我不同意。您将域设计为代表业务对象,为什么要在视图模型中再次抛弃它?始终考虑未来可能需要使用额外属性扩展您的域模型,以及您今天可以做些什么来降低此类更改的成本。如果要将域图层与表示层分开,请引入包含相同对象的DTO图层。在这些对象上,您可以应用数据注释和仅适用于表示层的其他内容。使用AutoMapper可以快速完成从域对象填充DTO。但是,请注意不要在/或使用这些DTO编写业务逻辑。
这是我的2美分。