据我所知,MVC通过作为控制器的“胶水”将类定义(模型)与表示(视图)分开。控制器应该有一个责任,因此是可测试的。 ViewModels用于汇集来自多个实体的数据,并从控制器“按摩”视图。
似乎业务逻辑并没有真正占有一席之地......所以我认为服务的另一层是合适的。我只是不确定在哪里放置这个层,或者如何构建服务 - 它应该是一个名为“services”的类,它包含一堆函数吗?我对MVC有点新意,所以任何阅读材料,样本或一般新人的提示都会很棒。
答案 0 :(得分:114)
在开发ASP.NET MVC应用程序时,我通常使用服务层。它类似于Martin Fowler在企业应用程序架构模式中讨论的Service Layer Pattern。它封装了您的业务逻辑并使控制器非常精简。基本上,控制器使用服务层来获取域模型,然后将其转换为视图模型。我还使用Unit of Work Design Pattern来处理事务,使用Repository Design Pattern来封装数据访问层,以便更轻松地进行单元测试,并且能够轻松交换ORM。此图显示了我在MVC应用程序中使用的典型层。
此图中的服务层标记为“应用程序或域层”,因为我发现当您使用术语“服务层”时,人们会感到困惑。他们倾向于认为这是一个Web服务。它实际上是一个可以由您喜欢的Web服务技术(如ASP.NET Web API或WCF)以及控制器使用的程序集。
至于命名约定,我通常使用描述域后跟服务的东西。例如,如果我有一个处理用户成员资格的服务层,那么我将有一个名为MembershipService的类,它具有控制器和Web服务所需的所有方法来查询和操作成员资格域。请注意,您可能在同一个应用程序中有多个域,因此您可以拥有多个服务层。我的观点是,您不必拥有一个负责整个应用程序的单一服务。
答案 1 :(得分:25)
我的建议是创建一个名为“services”的单独类。将它们放在不同的类库(或命名空间)项目中,使它们独立于MVC框架基础结构。我建议也使用某种依赖注入(最好的是构造函数注入)。那么您的服务类可能如下所示:
public class MyService : IMyService
{
IFirstDependency _firstService;
ISecondDependency _secondService;
public MyService(IFirstDependency firstService, ISecondDependency secondService)
{
}
public Result DoStuf(InputDTO)
{
// some important logic
}
}
然后从控制器中使用这些服务。 查看here以获取完整示例。
根据存储库 - 我的建议是,如果您要使用一些现代ORM(NHibernate,EntityFramework),请不要使用它们,因为您的业务逻辑将封装在服务层中,并且您的数据库将已使用ORM封装框架。
答案 2 :(得分:10)
答案 3 :(得分:8)
引自 “Business logic should be in a service, not in a model”?:
在MVP / MVC / MVVM / MV *架构中,根本不存在服务。或者如果它们这样做,该术语用于指代可以注入控制器或视图模型的任何通用对象。业务逻辑在您的模型中。如果要创建“服务对象”来编排复杂的操作,那么这被视为实现细节。遗憾的是,很多人都是这样实现MVC,但它被认为是反模式(贫血领域模型),因为模型本身什么都不做,它只是UI的一堆属性。
有些人错误地认为采用100行控制器方法并将其全部推送到服务中会使得架构变得更好。它真的没有;它所做的就是添加另一个,可能是不必要的间接层。实际上,控制器仍在进行工作,它只是通过一个命名不佳的“帮助器”对象来完成。我强烈推荐Jimmy Bogard的Wicked Domain Models演示文稿,以明确如何将贫血领域模型转变为有用的模型。它涉及仔细检查您正在公开的模型以及哪些操作在业务环境中实际有效。
答案 4 :(得分:3)