据我了解,MVC通过作为控制器的“胶水”将类定义(模型)与表示(视图)分开。控制器应负有单一责任,因此是可测试的。ViewModel用于将来自多个实体的数据汇总在一起,并“按摩”来自视图的控制器的数据。
似乎业务逻辑并没有真正的位置...所以我认为适合服务的另一层是合适的。我只是不确定在哪里放置此层,或如何构建服务-它应该是一个包含大量功能的称为“服务”的类吗?我对MVC有点陌生,因此任何阅读材料,样本或常规的新手技巧都很棒。
Answers:
开发ASP.NET MVC应用程序时,通常使用服务层。它类似于Martin Fowler在企业应用程序体系结构模式中讨论的服务层模式。它封装了您的业务逻辑,并使控制器变薄。基本上,控制器使用服务层来获取域模型,然后将其转换为视图模型。我还使用工作单元设计模式来处理事务,并使用存储库设计模式来封装数据访问层,以简化单元测试并能够轻松换出ORM。该图显示了我在MVC应用程序中使用的典型层。
在此图中,服务层被标记为“应用程序或域层”,因为当您使用术语“服务层”时,我发现人们会感到困惑。他们倾向于认为这是一个Web服务。实际上,它是可以由您喜欢的Web服务技术(例如ASP.NET Web API或WCF)以及控制器使用的程序集。
至于命名约定,我通常使用描述服务后域的名称。例如,如果我有一个处理用户成员资格的服务层,那么我将拥有一个名为MembershipService的类,该类具有控制器和Web服务查询和操纵成员资格域所需的所有方法。请注意,同一应用程序中可能有多个域,因此您可以具有多个服务层。我的意思是,您不必拥有一个照顾整个应用程序的整体服务。
我的建议是创建一个单独的类,称为“服务”。将它们放在不同的类库(或名称空间)项目中,并使它们独立于MVC框架基础结构。我建议也使用某种依赖注入(最好是构造函数注入)。然后您的服务类可能如下所示:
public class MyService : IMyService
{
IFirstDependency _firstService;
ISecondDependency _secondService;
public MyService(IFirstDependency firstService, ISecondDependency secondService)
{
}
public Result DoStuf(InputDTO)
{
// some important logic
}
}
然后,您可以从控制器使用这些服务。看看这里为完整的例子。
根据存储库-我的建议是,如果您要使用一些现代的ORM(NHibernate,EntityFramework),请不要使用它们,因为您的业务逻辑将被封装在服务层中,而您的数据库将已经被ORM框架封装。
在MVP / MVC / MVVM / MV *体系结构中,根本不存在服务。或者,如果确实如此,则该术语用于指代可以注入到控制器或视图模型中的任何通用对象。业务逻辑在您的模型中。如果要创建“服务对象”来编排复杂的操作,则可以将其视为实现细节。遗憾的是,很多人都这样实现MVC,但由于模型本身不执行任何操作,因此它被视为反模式(贫血域模型),它只是UI的一堆属性。
有些人错误地认为采用100线控制器方法并将其全部推入服务可以使体系结构更好。确实没有;它所做的只是添加另一个可能是不必要的间接层。实际上,控制器仍在进行工作,只是通过一个名称不正确的“ helper”对象进行的。我强烈推荐Jimmy Bogard的Wicked Domain Models演示,作为一个清晰的示例,说明如何将贫血的领域模型转变为有用的模型。它涉及仔细检查您要公开的模型以及在业务环境中实际上有效的操作。