Alex Rivera | Logout

Should controllers in an ASP.NET MVC web app call repositories, services, or both?

Asked 2008-12-03T21:39:51.537
20

The controllers in my ASP.NET MVC web app are starting to get a bit bloated with business logic. The examples on the web all show simple controller actions that simply pull data out of a repository and pass it to the view. But what if you also need to support business logic on top of that?

Say, for instance, an action that fulfills an order also needs to send an e-mail out. Do I stick this in the controller and copy/paste this logic to any other actions that also fulfill orders? My first intuition would be to create a service like OrderFulfillerService that would take care of all this logic and have the controller action call that. However, for simple operations like retrieving a list of users or orders from the database, I would like to interact directly with the repository instead of having that call wrapped by a service.

Is this an acceptable design pattern? Controller actions call services when they need business logic and repositories when they just need data access?

Edit
Report

2 Answers

27

Your controllers (in the MVC project) should be calling your objects in the Service project. The services project is where all the business logic is handled.

A good example is this:

public ActionResult Index()
{
    ProductServices productServices = new ProductServices();

    // top 10 products, for example.
    IList<Product> productList = productServices.GetProducts(10); 

    // Set this data into the custom viewdata.
    ViewData.Model = new ProductViewData
                         {
                             ProductList = productList;
                         };

    return View();
}  

or with Dependency Injection (my fav)

// Field with the reference to all product services (aka. business logic)
private readonly ProductServices _productServices;

// 'Greedy' constructor, which Dependency Injection auto finds and therefore
// will use.
public ProductController(ProductServices productServices)
{
    _productServices = productServices;
}

public ActionResult Index()
{
    // top 10 products, for example.
    // NOTE: The services instance was automagically created by the DI
    //       so i din't have to worry about it NOT being instansiated.
    IList<Product> productList = _productServices.GetProducts(10); 

    // Set this data into the custom viewdata.
    ViewData.Model = new ProductViewData
                         {
                             ProductList = productList;
                         };

    return View();
}

Now .. what's the Service project (or what is ProductServices)? that's a class library with your business logic. For example.

public class ProductServices : IProductServices
{
    private readonly ProductRepository _productRepository;
    public ProductServices(ProductRepository productRepository)
    {
        _productRepository = productRepository;
    }

    public IList<Product> GetProducts(int numberOfProducts)
    {
   
answered 2008-12-04T01:56:55.323
1

If you are going to have a business layer, then I think that it is best to have only the business layer talk to the data layer. I can understand why in a simple use case, you'd have the presentation layer (the controller) talk to the data layer directly, but once you identify a need for an isolated business layer, then mixing usage of the two in higher levels gets to be dangerous.

For example, what if controller A calls a method in the business layer to fetch a List of Object A (and this method applies the business rules - maybe some filtering or sorting), but then Controller B comes along, needs the same piece of data, but forgets about the business layer and calls the data layer directly ?

answered 2008-12-03T21:51:29.173

Your Answer