从内到外,这些是我们的MVC应用层:
一切都很好,直到我需要为第5步创建一个ViewModel来同时提供Razor视图以及JSON / Knockout ViewModel:
由于Controller无法直接访问存储库,这是否意味着我为每个允许编辑内容的视图创建服务?我需要从中获取POCO存储库以及每个字段类型的所有选项。
为每个视图创建单独的服务似乎是多余的。例如,viewModel用于编辑地址,而viewModel用于编辑也具有地址的房地产属性。我们可以有十几个表格来编辑同一个地址POCO。
为了使这个问题更容易回答,是否允许Controller直接访问存储库一个漏洞的抽象?
答案 0 :(得分:1)
那么,您的控制器是否会拥有将POCO从Entity Framework转换为单独的视图模型对象的代码?
如果是这样,那么您应该将该代码移到单独的类中,并遵循单一责任原则。该类是否在“服务层”中取决于您自己。您是否使用AutoMapper取决于您自己。但是这些data mappers不应该是控制器逻辑的一部分;控制器应尽可能愚蠢。
好的,现在让我们忽略数据映射问题,假装你可以直接使用你的POCO作为视图模型。那么你仍然想要一个服务层,因为它会在
之间转换userService.GetByUserName("bob")
在你的哑控制器中,并通过返回
以特定方式实现它userRepository.Users.Single(u => u.UserName == "bob")
<小时/> 将这些放在一起,您的
UserController
最终会接受IUserService
和IUserDataMapper
个依赖关系,并且代码非常愚蠢,根据需要:
public ActionResult ShowUserPage(string userName)
{
var user = userService.GetByUserName(userName);
var viewModel = userDataMapper.MakeViewModel(user);
return View(viewModel);
}
现在,您可以针对两个依赖项测试带有存根的控制器,或者在模拟IUserDataMapper
时存根IUserService
,反之亦然。您的控制器逻辑非常少,has only one axis of change。对于用户数据映射器类和用户服务类,也可以这样说。
今天早上我正在读一篇文章,你可能会发现这些建筑问题有些启发。它有点居高临下,标题为“Software Development Fundamentals, Part 2: Layered Architecture。”您可能无法从数据库应用程序模型切换到文章描述和建议的持久无知模型。但它可能会指出你正确的方向。
答案 1 :(得分:0)
我个人总是将存储库/存储库注入控制器。我不确定为什么你想要在存储库和控制器之间有一个服务层。如果有的话,你会使用规格。
完成后,请查看automapper。它是一个映射器,一旦正确配置,就可以将您的域模型映射到您的视图模型,然后再返回。