ASP.NET MVC:您在哪里组装视图的视图模型?

Zac*_*ott 7 repository-pattern asp.net-mvc-3

从内到外,这些是我们的MVC应用层:

  1. MS SQL /表/视图/存储过程
  2. 实体框架4.1(ORM)与POCO生成
  3. 知识库
  4. 服务(检索)和控制功能(保存)
  5. 路由 - >控制器 - > Razor View
  6. (客户端)使用Knockout.js(MVVM)的JQuery Ajax

一切都很好,直到我需要为第5步创建一个ViewModel来同时提供Razor视图以及JSON/Knockout ViewModel:

  • 包含所有下拉列表选项和下面字段选项的标题
  • Items - 我们发送给客户端的任何内容的数组,成为ViewModel

由于Controller无法直接访问存储库,这是否意味着我为每个允许编辑内容的视图创建服务? 我需要从存储库中获取POCO,并根据需要为每个字段类型添加所有选项.

为每个视图创建单独的服务似乎是多余的.例如,viewModel用于编辑地址,而viewModel用于编辑也具有地址的房地产属性.我们可以有十几种形式来编辑相同的地址POCO.

为了使这个问题更容易回答,是否允许Controller直接访问存储库一个漏洞的抽象?

Dom*_*nic 1

那么,您的控制器是否将拥有将 POCO 从实体框架转换为单独的视图模型对象的代码?

如果是这样,那么您应该将该代码移至单独的类中,并遵循单一职责原则。该类是否位于“服务层”取决于您。是否使用 AutoMapper 取决于您。但这些类型的数据映射器不应该是控制器逻辑的一部分;控制器应该尽可能愚蠢。


好的,现在让我们忽略数据映射问题,并假设您始终可以直接使用 POCO 作为视图模型。那么你仍然需要一个服务层,因为它会在

userService.GetByUserName("bob")
Run Code Online (Sandbox Code Playgroud)

在你的哑控制器中,并通过返回以特定方式实现它

userRepository.Users.Single(u => u.UserName == "bob")
Run Code Online (Sandbox Code Playgroud)


把这些放在一起,你UserController最终会接受IUserServiceIUserDataMapper依赖,并且代码是超级愚蠢的,如所希望的:

public ActionResult ShowUserPage(string userName)
{
    var user = userService.GetByUserName(userName);
    var viewModel = userDataMapper.MakeViewModel(user);

    return View(viewModel);
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用两个依赖项的存根来测试控制器,或者IUserDataMapper在模拟时进行存根IUserService,反之亦然。你的控制器几乎没有逻辑,并且只有一个变化轴。对于用户数据映射器类和用户服务类来说也是如此。


今天早上我读了一篇文章,您可能会发现它对这些架构问题有一些启发。它的标题有点居高临下:“软件开发基础知识,第 2 部分:分层架构”。您可能无法从数据库应用程序模型切换到本文描述和建议的持久无知模型。但它可能会为您指明正确的方向。