在大多数关于ASP.NET MVC的文档中,整个“关注点分离”都被大量推动。依赖注入/控制反转,单元测试,保持视图之外的“逻辑”等。
但这有多远意图推动?如果特定任务需要超出View / Model / Persistence“三层”方法的额外逻辑,这是不好的做法吗?
例如,我有一个包含四个单独项目的解决方案。
Project.Web (ASP.NET MVC) [ References Data.dll, Models.dll ]
Project.Data (Fluent nHibernate Mapping) [ References Models.dll ]
Project.Models (POCO, Helpers, Factories, etc)
Project.Tests (Unit Testing)
到目前为止,这对我很有帮助。但是我的一些MVC视图需要一些非常抽象的逻辑,因此我需要参与Models
并安排一个持久存储在数据库中的View Model
。
这在我的Data
部分中不会发生,因为这会释放它的可重用性,并且流程中包含业务逻辑。它不能完全发生在我的Models
部分,因为这需要它知道Data
部分,而不是Web
部分。我不想把它放在Project.Presentation
部分,因为我不想要那里的数据访问代码。
对我来说,添加引用Data.dll
和Models.dll
以构建我需要的{{1}}项目是否会严重违规?此外,除了项目问题之外,这一般是一种糟糕的方法,还是这种情况很多你有时会发现自己不得不这么做?我的一部分感觉如果我不得不诉诸于此,那么我只是错误地构建了我的软件 - 但同时我非常有信心我做了一个相当不错的工作,制作一个原始的太抽象了没有中间人安排的HTML解释。
答案 0 :(得分:2)
我使用以下结构,这或多或少地解决了我们在MVC结构方面遇到的所有问题。
网页流程将遵循以下流程:
在代码中,这看起来像:
// action
public ActionResult ListOfObjects () {
var model = new ServiceLayer.ObjectsClient().GetListOfObjects();
return View(model);
}
// Service Layer
public ListOfObjectsModel GetListOfObjects () {
var businessEntities = BusinessDao.GetThingysFromDb();
var model = Mapper.TranslateToViewModel(businessEntities);
return model;
}
// Mapping Layer
public ListOfObjectsModel TranslateToViewModel(List<BusinessEntity> entities) {
// do mapping
}
处理POST时,您将遵循相同的流程,但映射层应将ViewModel转换为提供给业务逻辑的数据实体。
答案 1 :(得分:2)
根据我的经验,单一责任是编写您希望尽早及经常更改的代码的好方法。和Jan一样,我在谁做什么的时候也有一条线。您执行此操作的次数越多,就越容易替换系统的一部分。我最近使用EF4.1删除了linq2sql,并且由于SRP,一旦我通过我的新EF4层进行测试,其他一切都正常工作。
那就是说,我通常让单元测试决定这些东西的存在 - 这是我的SRP驱动程序,并且询问基本问题“必须=类/服务=知道=其他东西=做它的工作吗?”如果答案是否定的,那么它会转移到其他地方 - 如果是,那就是依赖性。现在,如果它变得痛苦,那就是它告诉我“这是愚蠢的”(see this question for the stupid)的方式,我试图强迫某些东西,而不是让它符合它必须的方式。
在您的核心问题上:您已清楚地发现代码中存在差距 - 它必须知道两件事(数据和模型)并且我同意,它应该是它自己的东西并被拉出来。我将其称为“DomainService”或者可能只是DTO,但演示文稿感觉它不仅仅是准备数据。 (我认为视图会处理演示文稿......也许你会说服主持人?)。我也反对你认为你做错了“ - 不,你正在学习以不同的方式编写代码并允许它发展,完全应该如此。 : - )
答案 2 :(得分:1)
“参与模型并安排一个持久存储在数据库中的视图模型”
然后它不是一个视图模型。
这会简化事情吗?
答案 3 :(得分:0)
什么是'ViewModel':
“ViewModel”常常与持久性混淆。如果你仔细看一下这个词,它就是'View'+'Model'的组合 - 这实际上意味着它是满足你视图所有需求所需的单个数据单元。 ViewModel可以推断出多个实体或源来构建View所需的内容。
现在来看你的问题:
对我来说,添加一个引用Data.dll和Models.dll来构建我需要的Project.Presentation项目是否存在严重违规行为?
Re:如果必须这样做,我会在我的MVC项目中创建一个名为“ViewModels”的单独命名空间(文件夹),并将所有Viewmodel放在那里。在我看来,如果你希望你的ViewModel在一个单独的命名空间中,它实际上不会违反MVC。你只是在加强分离或使它更适合单元测试。
只需2美分!