我很好奇人们构建viewmodel的各种方法,以及他们为什么选择那种方法。
我可以想到几种方法:
1。注入的存储库——控制器加载模型并映射到ViewModel。在这里,ViewModel构造函数可以接受各种集合,以便在选择列表中进行内部设置,例如:
<>之前
public CustomerController(ISomeRepository repository)
{
_repository = repository;
}
public ActionResult Create()
{
CustomerCreateViewModel model = new CustomerCreateViewModel(_repository.GetShipTypes,
_repository.GetStates);
..
..
}
之前2。ViewModelBuilder——使用注入的存储库的实例在控制器中注入或实例化。通过像
这样的东西调用> var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);
或
var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);
3。直接在控制器中(不需要代码-它很乱)
4。一些其他服务(注入或不),返回域模型,然后映射控制器或ViewModel(任何人这样做,以返回一个视图模型,不是专门命名/标记为ViewModel构建器类?)
public JobCreateViewModel BuildJobCreateViewModel(int parentId)
{
JobCreateViewModel model = new JobCreateViewModel();
model.JobStatus = _unitOfWork.JobRepository.GetJobStatuses();
model.States=_unitOfWork.StateRepository.GetAll();
return model;
}
现在返回—关于验证视图模型—您是从基本ViewModel类继承标准验证,还是在所有ViewModel之间复制验证(例如数据注释属性),或者仅仅依赖于服务器端验证,以便它可以针对您的域对象进行验证?
还有其他的吗?什么更好的吗?为什么?
编辑根据下面的链接,我找到了一篇来自Jimmy Bogard的关于ViewModels架构的好文章。虽然它没有直接解决上面的问题,但对于任何来这里获取ViewModel信息的人来说,它是一个很好的参考。http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
我将服务注入到控制器中,而不是存储库中,然后使用AutoMapper将其转换为视图模型。在这种情况下,服务层的好处是,它可以将来自一个或多个存储库的多个简单操作聚合到一个公开域模型的单个操作中。例子:
private readonly ICustomerService _service;
public CustomerController(ICustomerService service)
{
_service = service;
}
[AutoMap(typeof(Customer), typeof(CustomerViewModel))]
public ActionResult Create(int id)
{
Customer customer = _service.GetCustomer(id);
return View(customer);
}
在这个例子中AutoMap是一个我可以编写的自定义动作过滤器,它在控制器动作之后执行,检查返回的对象并使用定义的AutoMapper映射将其映射到指定的目标类型。因此视图获得相应的CustomerViewModel作为模型类型。应该相当于:
public ActionResult Create(int id)
{
Customer customer = _service.GetCustomer(id);
CustomerViewModel vm = Mapper.Map<Customer, CustomerViewModel>(customer);
return View(vm);
}
只是有太多的管道和重复的代码可以集中。
我还建议你看吉米·博加德的让你的控制器上减肥的视频
我刚刚完成了一个项目,我们对#4做了一个变化。我们在控制器中注入了一个服务类。服务类持有对存储库和模型构建器类(我们称之为模型工厂)的依赖关系。
控制器调用到服务类,服务类处理业务验证逻辑,然后从适当的工厂获取视图模型。模型本身依赖于数据注释来进行输入验证。
这对我们的团队来说非常有效。有足够的关注点分离,允许开发人员在不影响彼此的情况下完成他们的工作,但它是可管理的,足以理解发生了什么。
这是我们第一次尝试,我们会坚持下去。我很想看看别人的反应。
我们的方法是将存储库注入到控制器中,并使用Automapper http://automapper.org/将其映射到ViewModel。我们的ViewModels包含数据注释属性,以允许在客户端进行验证。
我们在存储库上调用返回域对象(实体框架)的方法。域对象被映射到ViewModel。我们倾向于使用相同的ViewModel进行编辑和添加,因此只需要一次数据注释。其最简单的形式如下代码:
public ActionResult List(int custId, int projId)
{
var users = _userRepository.GetByCustomerId(custId);
var userList = Mapper.Map<IEnumerable<CMUser>, IEnumerable<UserListViewModel>>(users);
return View(userList);
}
我使用了一个服务层,它从控制器中隐藏域模型,从服务方法中返回ViewModels。这允许我在不影响客户端的情况下对域模型进行更改。