Creating a Service Layer for my MVC application?

2019-01-16 00:22发布

问题:

From what I understand, MVC separates the class definitions (model) from the presentation (view) via the "glue" that is the controller. The controller should have a single responsibility and therefore be testable. ViewModels are used to bring together data from multiple entities and to "massage" the data from the controller for the view.

It seems like business logic doesn't really have a place... so I'm thinking another layer for services would be suitable. I'm just not sure where to place this layer, or how to build the services - should it be a class called "services" that contains a bunch of functions? I'm a bit new to MVC, so any reading material, samples, or general newcomer kind of tips would be awesome.

回答1:

I usually use a Service Layer when developing ASP.NET MVC application. It is similar to the Service Layer Pattern that Martin Fowler discusses in Patterns of Enterprise Application Architecture. It encapsulates your business logic and make the controllers pretty thin. Basically the controllers use the service layer to get the domain models that are then transformed into view models. I also use the Unit of Work Design Pattern to handle transactions and the Repository Design Pattern to encapsulate the data access layer for easier unit testing and being able to easily swap out ORM's. This figure shows the typical layers that I use in an MVC application.

The service layer is labeled as the "Application or Domain Layer" in this diagram because I find people get confused when you use the term "Service Layer". They tend to think that this is a web service. It is actually an assembly which can be used by your favorite web service technology, such as ASP.NET Web API or WCF, as well as a controller.

As for naming conventions I usually use something that describes the domain followed by service. For example, If I have a service layer that handles user membership then I would have a class called MembershipService that has all of the methods needed by controllers and and web services to query and manipulate the membership domain. Note you may have several domains in the same application so you can have multiple service layers. My point being here that you do not have to have one monolithic service that takes care of the whole application.



回答2:

My advice is to create a separate classes called "services". Put them in different class library (or namespace) project and make them independent on MVC framework infrastructure. I recommend to use also some kind of dependency injection (the best is constructor injection). Then your service classes may look like:

 public class MyService : IMyService
 {
     IFirstDependency _firstService;
     ISecondDependency _secondService;

     public MyService(IFirstDependency firstService, ISecondDependency secondService)
     {
     }

     public Result DoStuf(InputDTO)
     {
         // some important logic         
     }
 }

Then you consume these service from your controllers. Look here for complete example.

According Repositories - my advice is to do not use them if you are going to use some modern ORM (NHibernate, EntityFramework), because your business logic will be encapsulated in the Service Layer and your database will be already encapsulated with the ORM framework.



回答3:

Take a look at the article from MSDN best practices.

Source code of the application in article can be found here.



回答4:

Quoting from “Business logic should be in a service, not in a model”?:

In an MVP/MVC/MVVM/MV* architecture, services don't exist at all. Or if they do, the term is used to refer to any generic object that can be injected into a controller or view model. The business logic is in your model. If you want to create "service objects" to orchestrate complicated operations, that's seen as an implementation detail. A lot of people, sadly, implement MVC like this, but it's considered an anti-pattern (Anemic Domain Model) because the model itself does nothing, it's just a bunch of properties for the UI.

Some people mistakenly think that taking a 100-line controller method and shoving it all into a service somehow makes for a better architecture. It really doesn't; all it does is add another, probably unnecessary layer of indirection. Practically speaking, the controller is still doing the work, it's just doing so through a poorly named "helper" object. I highly recommend Jimmy Bogard's Wicked Domain Models presentation for a clear example of how to turn an anemic domain model into a useful one. It involves careful examination of the models you're exposing and which operations are actually valid in a business context.



回答5:

Sounds like you'd be after something like a repository pattern. You can read about it here:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

This answer here may also help:

Best Repository Pattern for ASP.NET MVC