.NET Core MVC 中 ViewModel 存放位置及构造函数映射使用疑问
关于ViewModel存放位置与代码精简的问题解答
1. ViewModel的存放位置
- 中小型项目:在Web项目根目录新建独立的
ViewModels文件夹,按照控制器/业务模块划分子目录,例如ViewModels/Home存放HomeController对应的所有视图模型,ViewModels/Product存放产品模块相关的视图模型,和领域实体、数据库实体的存储目录严格分离,保证职责单一。 - 大型多模块项目:可以将ViewModel单独抽为独立的类库项目,供多个Web模块共同引用,避免重复定义相同的视图模型。
2. ViewModel构造函数的使用方案
2.1 构造函数做默认值初始化(如创建空列表)是非常推荐的做法
- 可以有效避免映射、视图渲染时因为空集合引发的空引用异常,也能减少重复的初始化代码,不需要每次创建ViewModel实例时都手动给集合属性new列表。
2.2 构造函数传入Model完成映射的适用场景
- 简单映射场景(仅字段赋值、无复杂业务判断):非常推荐这么做,直接将映射逻辑内聚到ViewModel内部,控制器代码可以大幅精简,不需要再维护一堆私有映射方法。
- 复杂映射场景(需要关联查询其他数据、做大量格式转换、依赖外部服务):不建议将逻辑塞到ViewModel构造函数中,会导致ViewModel职责过重,这时建议单独抽离独立的映射服务/静态映射类,统一存放映射逻辑,控制器仅负责调用即可。
针对你的代码的优化示例
优化后的MainViewModel定义:
public class MainViewModel { // 无参构造完成默认值初始化 public MainViewModel() { SomeModel = new SomeModel { SomeOtherType2 = new List<SomeType1>() }; } // 带参构造直接完成业务模型到视图模型的映射 public MainViewModel(List<SomeType1> someType1) : this() { SomeModel.SomeType1 = MapSomeType1(someType1); } public SomeModel SomeModel { get; set; } // 映射逻辑内聚到ViewModel内部 private List<SomeType1> MapSomeType1(List<SomeType1> source) { var result = new List<SomeType1>() { // 原有映射逻辑 }; return result; } }
优化后的控制器代码:
[HttpPost] public IActionResult Index(List<SomeType1> SomeType1) { var viewModel = new MainViewModel(SomeType1); return View(viewModel); }
调整后控制器完全不需要维护映射相关的私有方法,代码量会大幅降低。
内容的提问来源于stack exchange,提问作者Just J
相关产品推荐
相关产品推荐

