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:
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.
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.
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?
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.
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.
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.
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.
I personally subscribe to the logic of Number 3, allowing the controller to populate the Model (or View Model as is sometimes differentiated).
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.
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); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With