ASP.NET MVC with service layer and repository laye

2019-01-29 20:24发布

问题:

I am in the process of determining a fairly simple layered architecture for a .NET MVC application that has a repository layer and a service layer. I have found some fairly clear and simple examples, notably www.asp.net, and some questions and answers here, but I am looking for something that is a little simpler, suitable for small applications, but that uses different projects, to get the idea across. The example I linked to above has the repository and service as classes in the Models namespace. That just isn't enough of a clear separation for me to be able to illustrate it properly.

I have a separate project for the repository that implements interface IRepository. There is a separarate project for the Service that implements IService and takes an IRepository (constructor injection). The Service implements IService. It is enough for this example that the controller instantiate the service, no need for an IoC container just yet. Think of it as an intermediate step to understanding best architectural practices, part of a sequence that builds progressively to include dependency injection and possibly more layers.

The question is, where should I define IRepository and IService? Both the service and repository projects need to reference them, of course. It seems clear then that they should be defined in another project referenced by both the service and repository projects. If so, what would a good naming convention be? Something like XXXXContracts?

Likewise, for the data models passed between the presentation, service and repository layers, is it acceptable to have a separate project called XXXXModels referenced by all the layers? I understand that in some cases the models passed between the service and repository layer can differ from those passed between the service layer and the presentation layer, but the principle is the same.

I have found answers to similar questions here, but they tend to involve a more complicated architecture than what I have outlined here. I'm looking to achieve a really simple and clean illustration of the two layers that can be seen as a step or two above referencing the data layer and having business logic in the controllers, that's all. I know there is a strong and valid argument for going straight to the full-blown best practice, but not everyone is suited to making that jump in one go.

回答1:

Introduction

This is something I've asked myself as well. One burning question I always have is similar to yours;

what would a good naming convention be?

How should I name things? Should they go in folders or projects?

After searching around I suspect the answer is that it doesn't really matter. What's important is that you solution has some sensible architecture and that you try to follow good practices such as SOLID.

My ASP.NET MVC heroes on this topic are Jeffrey Palermo, Steve Smith and Jimmy Bogard.

Onion Architecture

Jeffrey Palermo discusses a combination of old ideas but brings them together and gives it the visually stimulating name of Onion Architecture (a recommended read). Jeffrey shows a good approach to the problem of where to put things. He explains that at the centre (or top) of your application you have your Core. This layer is where you should put interfaces such as IRepository and IService.

Almost all of your interfaces should go in the core and everything else (other projects) can all reference the core. This way everything knows the skeletal structure of the application without knowing the implementation details.

Try to have your UI layer reference as little as possible (within reason). In one of my applications my UI (MVC) layer only references the Core. Everything it needs is injected into it with Dependency Injection.

Steve Smith discusses Onion Architecture and similar ideas with demonstrations in MVC Solution Best Practices: A solution to the solution problem

My solution

In my MVC solutions I have a typical structure like this:

  • MyProject.Core
  • MyProject.Domain
  • MyProject.DependencyInjection
  • MyProject.Infrastructure
  • MyProject.Web
  • MyProject.Tests

The Core contains my interfaces. It is usually divided up into folders like Services, Models, Domain, Repositories and so on.

The Domain layer references only the core and contains my implementation. It provides a lot of the concrete classes for the domain abstraction in the core. It deals with a lot of business logic, processing, command handling, manager classes, concrete service implementations and so on. I consider it a fairly inner-layer and so it references as little as possible.

The DependencyInjection layer contains my chosen DI package/framework and implementation details. I consider it an outer layer; similar to UI or Infrastructure and so it's ok if it references a lot. It's not necessary for this layer to be a separate project and many people will tell you not to do this. That's ok; do what works for the complexity of your project. I like my DI to be its own thing. The good thing about it being so separate is that I could replace the DI framework with a different one and things would be fine. No layers reference the DI project.

The Infrastructure layer contains information about logging, emailing and data access. It will contain my ORM of choice. It's not business-logic stuff and it's not UI stuff. It's the railroad of my solution to get things done. It's on the outer layer but it only references the Core.

The Web layer is my MVC project and only references the Core.

Complexity and final thoughts

I have found answers to similar questions here, but they tend to involve a more complicated architecture than what I have outlined here

It's a good point. It's important to keep in mind the complexity of your problem. But don't be deterred by good solution practices. My solution and Onion Architecture are not necessarily very complex and don't really bloat your solution. They just keep things separate.

In Evolutionary Project Structure, Jimmy Bogard talks about things being over-complex. If what I've said seems too complex, follow Jimmy's advice and put it all in the one project (your UI layer). That's ok - as long as it suits you.

Remember to take my solution only as an idea - something to consider; my approach is an attempt to follow sage advice from the best, but I'm sure I've only succeeded so much; I can (and must) still improve.