4

In MVC the Domain Models(from Model Layer) should instantiate other Domain Models or all the Domain Models should be instantiate in the controllers and passed down using Dependency Injections?

How do you implement this in real applications? If you choose this path isn't the controller getting to fat?

  • 2
    Can you reword your question, as it is a little bit confusing? – Gibson Aug 14 '13 at 14:31
3

In .NET context, MVC is a framework for building websites.

  • M(Model) refers to a viewmodel, i.e. it's a data structure that will be used specifically for display purposes. Examples of view models:

    • DisplayCustomerViewModel - data structure that has everything required for displaying customer information

    • DeleteCustomerViewModel - data structure that has everything required for removing customer (probably id and customer name for confirmation purposes).

  • View models are different to your domain model. If you don't understand it, then read it again and do some research.

  • You shouldn't use your domain models instead of view models, period.

  • If you view model and domain model are the same (for now anyway), then just copy data from domain model into view model (use auto mapping framework to save you time).

V(iew) refers to a page that should have a dependancy on your view model (M). Its sole purpose is to display data stored in that view model.

C(ontroller) in my eyes should:

  • Call a business layer to get data or update data. See example below.

  • Business layer should then return a result of the operation.

  • Controller takes the result and maps it to the view model.

  • Controller decides whether to simply display view model, re-direct user or do something else.

  • At no point controller should be doing any business logic.

  • Ideally, you should not reference the domain layer in your MVC project (presentation layer) at all. This way you won't confuse domain models with view models.

Example of what I consider to be a good controller action:

public ActionResult UpdateCustomer(UpdateCustomerViewModel updateCustomerViewModel)
{
   if (!ModelState.IsValid)
      return View(updateCustomerViewModel);

   // I create a DTO that holds customer information necessary to do the update. I copy values from my view model to my DTO object.
   var updateCustomerDTO = AutoMapper.Map<UpdateCustomerDTO>(updateCustomerViewModel);

   // I have a command that encapsulates customer update logic. This command 
   // is in a business layer and it knows nothing about view models.
   // Dependency is a static class that exposes IoC container. 
   // normally I would set my commands through constructor though.
   var updateCustomerCommand = Dependency.Resolve<IUpdateCustomerCommand>();

   // When command executes, it produces a result. Result may be as simple as 
   // true (success) and false (failure). I however chose to have a custom
   // type representing a result of the command.
   var result = updateCustomerCommand.Execute(updateCustomerDTO);

   // Self explanatory
   if (result is SuccessfulCustomerUpdate)
      return Success();

   return Failure();
}

Just to recap the flow:

  • View model is mapped to DTO
  • DTO is passed to the business layer
  • Business layer extracts data from DTO and does some work by talking to domain layer (Domain models)
  • Business layer sends back DTO or some kind of result object
  • Presentation layer takes data out of DTO or result object and maps it to the view model
  • Presentation layer displays the view model
1

From what I can grasp of your questions is, you should look into is using an Application Service Layer between your Controller and your Domain Model. Your controller would use Dependency Injection for the Application Service.

The service would then orchestrate your domain and contain no business logic. The service layer acts as a boundary between your controller and domain model. The orchestration aspect would include how your domain models get instantiated.

--MVC/UI layer

public UserController: Controller
{
    private readonly IUserService _userService;
    public UserController(IUserService userService)
    {
         _userService = userService;
    }

    public void SomeUserAction()
    {
        _userService.SomeUserAction();
    }

}

-- Service Layer

public UserService : IUserService
{
    public void SomeUserAction()
    {
         //Orchestrate domain logic
    }
}

Doing it this way prevents your controller getting fat. The controller only holds references to each Application Service that it requires.

Martin Fowler has a nice article on the Service Layer

  • All controllers should have a service then? – danidacar Aug 15 '13 at 16:04
  • If you controller is accessing your domain model, I would put in a service. It is also possible to have multiple services in a single controller, if so required. Try not to bloat your services by having one per controller and putting all controller logic in your service. Having services dedicated to a task or action is best. IUserService/IAccountService/IOtherService can all be used in a single controller – Gibson Aug 15 '13 at 16:07
  • should I instantiate models inside services? – danidacar Sep 16 '13 at 18:34
  • Domain models - Yes (although more than likely could be from a repository). View Models - No. View Models should be instantiated via the controller. Controller calls service layer, hence gets domain data, then it maps to View Model data. Returns View Model to the View. Quick SO search: stackoverflow.com/questions/9331053/… and stackoverflow.com/questions/3002168/… – Gibson Sep 17 '13 at 12:29
  • This is how I do it. I use dependency injection in all my apps, it just makes so much sense. – The Muffin Man Sep 30 '13 at 19:02
0

In standard MVC Models should not know anything about other Layers, including other Models. It is the job of Controller to instantiate them.

Unfortunately, the link to "Service Layer" provided in the other answer only leads to a very sketchy outline, directing the reader to the book for more details. In fact, I could not find a good detailed information on it, so maybe the concept is not so widely used? But from what I see, it just looks like another kind of Controller, maybe of higher hierarchy, that orchestrates other Controllers.

You can write a dedicated Controller to instantiate all your Models, or it it gets too large, add individual Controllers for certain Models.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.