你如何填充/验证你的ViewModels?

时间:2011-10-30 02:57:58

标签: asp.net-mvc asp.net-mvc-3 model-view-controller viewmodel

我很好奇人们构建ViewModel的各种方式以及他们选择该方法的原因。

我可以在这里想到几种方法:

-1。注入的存储库 - 控制器加载模型并映射到ViewModel。在这里,ViewModel构造函数可以采用各种集合来为ex设置。在选择列表中,例如:


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/

4 个答案:

答案 0 :(得分:14)

我将服务注入控制器而不是存储库,然后使用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);
}

只是它太多的管道和重复的代码可以集中。

我还建议你观看Jimmy Bogard的putting your controllers on a diet video

答案 1 :(得分:1)

我刚刚完成了一个项目,我们在#4上做了变化。我们将一个服务类注入到控制器中。服务类依赖于存储库和模型构建器类(我们称之为模型工厂)。

控制器调用服务类,它处理业务验证逻辑,然后从适当的工厂中获取视图模型。模型本身依赖于数据注释进行输入验证。

它对我们的团队非常有效。有足够的关注点分离,允许开发人员在不影响彼此的情况下完成工作,但它足以理解发生了什么。

这是我们第一次尝试它,我们会坚持下去。我很想知道其他人的回应。

答案 2 :(得分:0)

我们的方法是将存储库注入控制器,并使用Automapper http://automapper.org/将其映射到ViewModel。我们的ViewModels包含数据注释属性,以允许在客户端上进行验证。

我们在存储库上调用返回Domain对象(Entity Framework)的方法。域对象映射到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);
    }

答案 3 :(得分:0)

我使用一个服务层来隐藏控制器中的域模型,从服务方法返回ViewModels。这允许我在不影响客户端的情况下对域模型进行更改。