Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
I have a drop down list that displays values from a table to the end user. I would like to have these values be sorted alphabetically.
According to proper MVC design, at what layer should I place my sorting logic: the model, the view, or the controller?
EDIT: In response to LarsH's question, "Do you mean code that determines what sort order is desired? or code that performs the sort?", I was originally referring to the code that determines what sort order is desired.
回答1:
(Note: this quote and citation is taken from @dasblinkenlight's answer, but we disagree on our interpretation of it. read his post and make up your own mind).
According to MVC description,
A controller can send commands to its associated view to change the view's presentation of the model (for example, by scrolling through a document). It can send commands to the model to update the model's state (e.g. editing a document).
Sorting logic (e.g., the sorting comparator/sorting algorithm) belongs in the model since it contains business rules and state data. Since altering the way the model data is sorted falls squarely into the "change the view's presentation of the model" category, the controller is responsible for "doing the sorting" by calling the model.changeSortedState() method.
回答2:
Who controls the sort order?
(From Wikipedia)
1) Natural order within the data itself:
The order is part of the Model, so it should go there. A raw pull of "all data" would return the data in the sorted order, and there is no interface to choose the sort order.
2) The user should control how they see the data:
The View would provide an interface (such as ascending/descending arrows) that interact with the Controller, and the Model understands the data well enough to do the requested sort on the data. However, a raw pull of the data doesn't necessarily have to be sorted, unlike in (1).
In either case,
The View doesn't understand that there's a sort going on, other that the ability to show which sort direction has been chosen. Don't put the logic there.
Small caveat
The sorting functionality could go purely in the View, under one circumstance (that I can think of offhand; there may be more):
A "dumb" sort where all the data is already in the view and it doesn't have to use any domain knowledge to do the sort. Very simple string or number comparison, for example. This is not possible in, for example, search results on a webpage when results are likely to be split across multiple pages.
回答3:
According to MVC description,
A controller can send commands to its associated view to change the view's presentation of the model (for example, by scrolling through a document). It can send commands to the model to update the model's state (e.g. editing a document).
According to this, sorting logic belongs in the controller, because altering the way the model data is sorted falls squarely into the "change the view's presentation of the model" category.
EDIT: To clarify multiple misunderstandings voiced in the comments, the "sorting logic" is not the code that performs the sort; it is the code that defines the sort. The sorting logic compares individual items to each other to establish an order (e.g through an instance of IComparator<T>) or contains logic that constructs an object to be used for ordering by an external system (e.g. through an instance of IOrderedQueryable<T>). This logic belongs in your controller, because it needs knowledge related to the "business" side of your application. It is entirely sufficient to perform the sort, but it is separate from the code that actually performs it. The code that sorts may be in your view, in your model, or even in the persistence layer that backs your model (e.g. your SQL database).
回答4:
None of the above. Sorting is business logic, and business logic doesn't belong in any of the three. Not every piece of code in your application will be a model, view, or controller.
What I generally do in my MVC apps is I have a service layer that performs all the business logic. The methods in the service layer should have a clean, simple API with well named parameters. You can then invoke those methods from your controller to manipulate the data in the models.
In that sense, the sorting is "in the controller", but the code itself that does the sorting should not be implemented in the controller, only invoked from there.
回答5:
Definetly not the controller: It sends messages to view and model but should do as little work as possible. If the user can change the sorting that request gets handled by the controller by informing the model or the view about it.
Maybe the View if it is a pure View thing. If the Application works just as well without sorting then the sorting is just part of the representation and should go in the view.
If the ordering is inherent part of the domain it should go in the model.
回答6:
Views are the part of MVC which is supposed to contain presentation logic.
Model layer is where business logic is contained.
Controllers only change the state of both, based on user input.
So the choice is - do you think that this is part of the domain business logic or presentation logic.
If you were implementing a proper MVC Model2 or classical MVC pattern, then I would say that the ordering of data provided by the model layer should be triggered by the view's request to the model layer. View asks for ordered data, model layer provides it.
But, since you are using ASP.NET MVC's interpretation of MVC pattern, which is a bit different then your standard MVC - the ViewModel instance should request ordered information from the model layer (for some reason ASP.NET framework thinks that templates should be called "views" and views should be called "viewmodels" .. it's strange).
回答7:
I would usually do it in the controller to remain in line with the pattern as per the other answers. See below for reasoning.
I've been mulling this over and reading the answers and related material and pragmatically speaking I would say it would depend on your application for instance:
Is it a medium/large application and/or has multiple UI's associated with it (i.e. a Windows App, Web interface and Phone interface).
In this case I would probably construct a service layer and put it in
the business object and then call the appropriate method from the
controller.
If its a well defined single UI website and you're using something like EF Code First and you do not have or have no intention of creating a service layer and plan on using a simple out of the box Extension method to acheive it:
In this case I'd probably put it in the controller as pragmatically
its the best fit with regard to time/budget.
If its the same as the above BUT cannot be implemented with an out of the box extension method.
I may well choose to pop it in the Model class (if its truely bespoke
to that single type) as it would be more appropriate here than in a
controller. If the sort could be applied to more than one class then
I'd implement it in an extension method and then call it in the
controller.
To sum up:
Dogmatic answer: Service Layer
Pragmatic answer: Usually the controller
回答8:
I would suggest sorting data from a table-data that is small enough to be useful in a dropdown list-should come from the DB already sorted via the query. To me, that makes the model the place the sort is applied.
If you are determined to do the sort by hand, I think there are good arguments for using either the model or controller as your preferred spot for logic. The limitation would be your particular framework. I prefer to manage data solely in the model. I use the controller to marry data(model) and presentation(view) as I've been (self)taught.
回答9:
Whilst I agree in principle with the idea that sorting is Business Logic because by breaking it down to it's origin you would end up with something like "The client would like the Product page to display with the images sorted by date" then it becomes clear that the sort order for data is typically not arbitrary - even if there is no sorting as that's still a business decision by omission (an empty list is still a list).
BUT... These answer don't seem to take into account the advances in ORM technology, I can only talk in relation to the Entity Framework (let's avoid an argument about whether this is true ORM, that's not the point) from Microsoft as that's what I use, but I'm sure other ORMs offer similar functionality.
If I create a Strongly Typed view for a Product class using MS MVC and the Entity Framework and there is a foreign key relationship between the Product and Image table (e.g. FK_Product_Image_ProductId) then I would out-of-the-box be able to quickly sort the images during their display using something like this in the view:
@foreach(Image i in Model.Image.OrderBy(e => e.DisplayOrder)){ //etc etc... }
There was mention of a specific Business Logic layer, which I also use to perform 80% of my business logic, but I'm not going to write sort functionality into my Business Logic layer that mimics something that comes out-of-the-box from the Entity Framework.
I don't think there's a correct answer to this question, other than to say that; you should abstract complex business logic where possible but not at the cost of reinventing the wheel.
回答10:
Assume that you have MVC website, WebForms website and a mobile application.
If you want sorting to be consistent between these presentation layers, then I'd say sort outside of the presentation layer. Service would be a good candidate.
Otherwise, I would store that logic in a view model. Why? Because it'll be reusable and easily testable.
回答11:
Out of the three you have listed, I would say that it belongs in the controller. I don't really like placing this sort of logic in the controller, though. I usually create a service layer that the controller communicates with that will be responsible for communicating with the data store and handling sorting logic. For small applications it is fine sitting in the controller, though.
回答12:
This is a question asked with the asp.net in mind, but since somebody did mention Rails, I thought it would be interesting to consider the problem in that context. In Rails, it is natural and pretty common to perform the sorting along with the retrieval as a controller action, since the framework and ActiveRecord/ActiveQuery api provisions for it. On the other hand, it is possible to define some sort of custom sort order for static items and put that in the model to be used by the controller, so the model can play a part in the sorting logic even though it does not carry out the operation directly. Whatever it is, it can be safe to say that putting the sort logic in the view is generally frown upon.
I'm slightly amused that some answers are absolutely against putting the sort in either the controller or the model, and I find them too pedantic for my taste, but I suppose it depends on the nature of the framework used and the usual conventions associated with it. I also agree with Bill K's comment that having the separation in the first place is more important.