Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct use of Model vs Controller in MVC / ASP.NET MVC

I have a Service class with a method called GetProducts(). That encapsulates business logic and calls the repository to get a list of products.

My MVC view wants to show that list of products as an MVC SelectList. Where is the correct place for that logic to go. I seem to have 3 options:

  1. Model

    The Model should expose a property called ProductSelectList. When the getter of this property is called by the View, the Model should call Service.GetProducts() and convert the result to a SelectList before passing it on.

    Plausible argument: The Model should make calls to business logic and the repository. The View should merely render predetermined data. The Controller should not be involved, save for passing contextual data to the Model.

  2. View

    The View should contain code that calls Service.GetProducts() directly and converts the result to a SelectList inline.

    Plausible argument: The View should call for this data directly as it is specifically for use on the View. There is no need to involve the Model or Controller, as we are calling an abstracted Service method anyway, so anything else just adds extra overhead.

  3. Controller

    The Controller should make the call to Service.GetProducts(), convert the results to a SelectList and pass it through to the Model, which should contain a simple ProductSelectList property. The View will access this property for rendering.

    Plausible argument: The Controller knows which parameters to provide to the Service method, so it should make the call. The Model should be a simple placeholder for data, filled by the Controller. The View's job is to simply render the data from the Model.

I have a feeling that the correct answer is Model, but the other two make some reasonable points. Perhaps I've muddied the waters by already having a Service class that's separate to the Model?

Would anybody care to share their opinion? Is this just a matter of taste?

like image 860
James McCormack Avatar asked Aug 10 '11 20:08

James McCormack


People also ask

What is the difference between controller and model?

The model is responsible for managing the data of the application. It receives user input from the controller. The view renders presentation of the model in a particular format. The controller responds to the user input and performs interactions on the data model objects.

What is the use of model in MVC?

The Model is the part of MVC which implements the domain logic. In simple terms, this logic is used to handle the data passed between the database and the user interface (UI). The Model is known as domain object or domain entity. The domain objects are stored under the Models folder in ASP.NET.

How can use model class in controller in MVC?

In Solution Explorer, right-click the Controllers folder and then click Add, then Controller. In the Add Scaffold dialog box, click MVC 5 Controller with views, using Entity Framework, and then click Add. Select Movie (MvcMovie. Models) for the Model class.

What is purpose to separate model view and controller in MVC concept?

The reason for separation of Models, Views, and Controllers revolves around the idea that most development for enterprise applications is done by a team of developers. Imagine 10 developers trying to work on your controller. But all they want to do is add something to the model.


2 Answers

I personally subscribe to the logic of Number 3, allowing the controller to populate the Model (or View Model as is sometimes differentiated).

  • I have my views dumb and only displaying data.
  • I have my View Models store the information that the View will need, occasionally exposing 'get only' properties that format other properties into a nicer format. If my model needs access to my services, then I feel I'm doing something wrong.
  • The controllers arrange and gather all the information together (but do no actual work, that is left for the services.

In your example, I would have my controller action similar to:

public ActionResult Index() {     IndexViewModel viewModel = new IndexViewModel();     viewModel.ProductSelectList = new SelectList(Service.GetProducts(), "Value", "Name");     return View(viewModel); } 

and my view model similar to:

public class IndexViewModel() {    public SelectList ProductSelectList { get; set; }    public int ProductID { get; set; } } 

With the appropriate part of the view looking like:

@Html.DropDownListFor(x => x.ProductID, Model.ProductSelectList); 

This way I'm content that I know where to look if there is an issue with anything and everything has a very specific place.

However, there is no correct way as seems always to be the case with these things. Stephen Walther has a good blog series on MVC tips. In one he talks about the View Model emphasis and although not a SelectList he populates, the SelectList is still data in much the same way his list of products is.

like image 138
Amadiere Avatar answered Sep 28 '22 09:09

Amadiere


In a classic MVC architecture your Model shouldn't be much more than a container for your view data hence the reason it's often called a ViewModel. A ViewModel is different from the Entity Model(s) that your service layer manages.

Your controller is then responsible for populating your ViewModel from the entity model(s) returned by your service layer.

Due to convenience some developers will use their service layer entities directly in their ViewModels but long term that can lead to headaches. One way around that is to use a tool such as AutoMapper to automate the shuffling of data to and from your ViewModel and entity models.

Here's what a controller might look like. Notice that data such as the SSN does not get exposed to the view since there is a mapping from your Entity Models to your View Model.

public class Customer : IEntity {   public string CustomerID { get; set; }   public string SSN { get; set; }   public string FirstName { get; set; }   public string LastName { get; set; }       public Address Address { get; set; } }  public class CustomerEditViewModel {   public string FirstName { get; set; }   public string LastName { get; set; }   public string Address1 { get; set; }   public string Address2 { get; set; }   public string Country { get; set; }   public string City { get; set; }   public string State { get; set; }   public string Zip { get; set; }   public string PhoneNumber { get; set; } }  public class CustomerController {   [AcceptVerbs (HttpVerbs.Get)]   public ActionResult Edit ()   {     Customer customer = _customerService.GetCustomer (User.Identity.Name);      var model = new CustomerEditViewModel ()     {       FirstName = customer.FirstName,       LastName = customer.LastName,       Address1 = customer.Address.Address1,       Address2 = customer.Address.Address2,       Country = customer.Address.Country,       City = customer.Address.City,       State = customer.Address.State,       Zip = customer.Address.Zip,       PhoneNumber = customer.Address.PhoneNumber,     };      return View (model);   } } 
like image 26
Todd Smith Avatar answered Sep 28 '22 10:09

Todd Smith