我可能在这里过分分析了,但是我在MVC上所做的所有阅读,似乎都有很多关于如何做事的意见。
是否有“最佳实践”网站或文档定义了每个MVC的责任?
我遇到的几个问题,请记住我使用的是EF / Repository& UnitOfWork / Service模式:
1)如何将域对象和业务规则的验证结果(错误消息等)从服务层获取到视图模型?
2)我正在使用域对象和一个完成所有业务逻辑的服务层,然后我将域对象发送给控制器并让它们(通过AutoMapper)将它们转换为视图的视图模型。控制器还有哪些其他类型的东西?以下代码可以吗?控制器中的逻辑太多了吗?:
public ActionResult SomeAction()
{
var model = Mapper.Map<DomainObject, ViewModel>(service.QueryReposForData());
model.SomeCollectionForSelectList = Mapper.Map<IEnumerable<DomainObject>, IEnumerable<ViewModel>>(service.QueryReposForSelectListData());
return View(model);
}
我不认为控制器中唯一的东西是一行返回一个视图,其中一个对象图被映射到视图模型?
3)我认为在ViewModel上有属性可以指示视图是否可以隐藏某些东西,然后在视图中执行该逻辑?例如:
@if(Model.DisplaySomething)
{
<div>Something to show</div>
}
else
{
<div>Something else to show</div>
}
4)我正在考虑让我的服务在写入时将某种TransactionResult
对象返回给控制器,以使其负责处理事务的服务。所以我会有一个聚合服务,它会启动一个事务(UnitOfWork)执行它需要做的事情,然后返回可能有错误消息的TransactionResult
?我不认为我应该让控制器负责管理事务,而是让它只是将映射到域对象的视图模型传递给服务并让它作用于它?
5)另外,你想用多少ActionFilter?我知道这是一个巨大的可扩展性点,但我经常发现自己试图将所有模型创建填充到过滤器中。
答案 0 :(得分:3)
根据我们的工作方式,提出意见。
几乎在所有情况下,我们都会让控制器变得很脆弱,而且几乎在所有情况下都是厌食症。
对于ViewModels,我们遵循为每个视图设置ViewModel的模式。 Controller会根据需要加载它,然后将其踢掉。从那里,ViewModel驱动一切。在我们的世界中,ViewModel直接绑定到视图,并且不包含将在应用程序的其他部分中使用的代码。它与需要的较大“模型”(服务层等)的任何部分进行交互,并打包以供View使用。
对于你的#3例子,我绝对肯定 - 这是我们使用ViewModel的方式。
同样,这一切都不是福音 - 只是我对如何处理它的看法。
答案 1 :(得分:3)
优秀的问题!
1)如何获取Domain的验证结果(错误消息等) 从服务层到视图模型的对象和业务规则?
我在后端使用EntityFramework,并在我的模型和实体上实现IValidatableObject。在模型上,我执行跨字段验证,而在实体上,我执行跨实体验证。
2)我正在使用域对象和一个完成所有操作的服务层 业务逻辑,然后我将域对象发送到控制器和 让他们(通过AutoMapper)将它们转换为视图的View Models。 控制器还有哪些其他类型的东西? 以下代码可以吗?控制器中的逻辑太多了吗?:
这段代码很完美。控制器收集数据,将数据转换为模型并将它们提供给视图。
3)我认为可以在ViewModel上拥有属性 指示某个视图是否可以隐藏例如然后 在视图中执行该逻辑?例如:
是的,这正是ViewModel的用途。捕获视图渲染所需的所有数据和逻辑。
4)我在考虑让我的服务恢复某种程度 TransactionResult对象在写入时返回控制器来实现它 服务处理交易的责任。所以我 会有一个可以启动交易的聚合服务 (UnitOfWork)做它需要做的事情,然后返回它 TransactionResult可能有错误消息?我不认为我 应该让控制器负责管理交易, 而是让它只传入映射到域对象的视图模型 服务并让它采取行动?
我在项目中有点挣扎。最后,我将EntityFramework的SaveChanges方法移到了前端。这允许我在前端构建一个事务然后提交一次。我的ApiController中执行更新,创建或删除的每个方法也会执行SaveChanges。
我使用ApiControllers作为后端和实际Controller类之间的抽象层。详细说明,我的应用程序都使用普通控制器(HTML)和ApiControllers(REST又名Web API)。两种类型的控制器共享用于检索数据的公共接口。
示例:http://pastebin.com/uL1NGGqH
UnitOfWork仍然位于幕后的后端。我只是将SaveChanges暴露给前端。诸如ValidationExceptions之类的副作用由ASP.NET MVC自动处理或在自定义ActionFilters中捕获。
5)另外,你想用多少ActionFilter?我知道这是一个 巨大的可扩展性,但我经常发现自己想要所有东西 将模型创建成过滤器。
我在目前正在进行的大型MVC项目中只使用了少量ActionFilters。这些ActionFilter主要用于强制执行安全性并将Exceptions(例如ValidationExceptions)转换为JSON格式,因此我的客户端验证框架可以处理它。
偏离主题:你永远不能过度分析。问自己这些MVC的基本问题可以让你更好地掌握MVC的概念,并使你成为一个更好的开发人员。只要确保你在老板的时候不要做太多事情;)
答案 2 :(得分:1)
同样在这里:
我真的不太关心实现UnitOfWork或显式使用事务,因为EF4会自动创建(如果它不存在)一个新事务,用于在 SaveChanges ({{3})内完成的所有更改我只有一个通用接口,将Context的DbSets暴露为IQuerable和Add / Delete / Find方法。
但正如所说,这一切都是个人的。