ASP.NET MVC - Problems with Separation of Concerns
Why is the ViewModel's part in the scheme of things so hard to understand?
Often in ASP.NET MVC, the term ViewModel is confused with the ViewModel of the MVVM pattern. This problem surfaced itself with this programmer's very astute question about the separation of concerns when trying to design an application solution. This person found the role of the ViewModel in ASP.NET MVC confusing and problematic.
I try to clarify this matter by showing that the ViewModel used in the ASP.NET MVC Pattern is not the same thing as the ViewModel in the MVVM pattern. they just happen to share the same title.
Read on, and be sure to offer your comments on the subject.
Turtoise, the questioner said:
I'm trying to get into ASP.NET MVC so I've already started to search what are the best design practices and how to implement them.
So, there's this question bothering me lately: what are the best ways of maintaining separation of concerns in MVC and MVVM?
I did some research and read quite a few articles/tutorials, but some of the approaches simply contradict each other and I've got the impression like there are no real guidelines to it, that's why I'm even asking in the first place.
In this response I would like to point out to the original poster that ASP.Net MVC does not implement the MVVM Pattern. The separation of Concerns in the MVVM pattern are a completely different discussion.
His actual questions are answered further down in this article. At this point I wanted to point out one of the misconceptions many folks have about the MVC pattern as posted by another respondent:
this is a very broad question. Here's a small bit of help. separation of concerns is about breaking your application into logical components so that maintenance is easy. Data layer connects to the database to retrieve data, business layer, gets data from datalayer, and does business logic to it, UI layer gets the info from the business layer. The UI layer in MVC has 3 components, The VIEW which is the html, the CONTROLLER, the part that gets the data and packages it up in the model, and the MODEL, the packaged data the UI will use in the view. Im out of room here, hope that helps a little.
heh, this could be the start of a long and possibly contentious conversation on MVC...First, IN MVC there is only one UI component, The View. The Model on the other hand represents the Business State. Not the Business logic, but the Business state. Finally, the Controller manages UI requests which include applying business logic, changes to business state, and the resulting changes to the view. This is MVC in it's purest form. As for Turtoise's confusion on the subjet, no surprise there I went to the MVC wiki and found the disussion on the architecture pattern wrong and refelcting common mistakes rather than fact IMHO.
The Model-View-Controller (MVC) pattern has a variant called Model-View-ViewModel (MVVM) Pattern wherein the ViewModel displaces the Controller in that while acting like a controller, it is usually View Specific where a controller determines what view to display. Also in the MVVM pattern the ViewModel provides both the business state and view state information directly to the View. IN this pattern, the ViewModel handles business state changes and business logic. It’s actually A controller tightly tied to a view. If the View request involves a change in view, it also involves a change in the controlling ViewModel. This is not neccesarrily true in the MVC pattern. In MVC, changes in the controller occur when the View requests A change to A different business model/logic. (something like Customer Controller to InvoiceController) It’s important to note here that the MVVM pattern is not implemented in ASP.Net MVC.
In the ASP.Net/MVC world there is still yet another deviation (of sorts) to the MVC pattern where the term ViewModel is used in the context of a controller specific Model. It does not usually perform any business state changes, the Controller is still in charge of managing business logic and business state changes. What the ViewModel has come to mean in MVC is that the business state and view state is being presented to the view in a model specific to the controller rather than specific to a given view.
Am I opinionated on this subject? YEP! When talking about separation of concerns, you have to understand the component concerns and know what they are before you can actually separate them as they should be.
So lets look at the questions;
First of all: how should creating view models be handled? Should view models be created via constructors with model-type arguments? Or maybe the entire logic of creating a view model out of model should be contained within a controller? Some people even suggest passing the model directly to the view, but that seems completely out of place to me, considering MVC is about separating those, right?
A ViewModel in the ASP MVC context is just a data model and only a datamodel. The instancing and populating of the ViewModel should be managed by the Controller, then passed to the View. Do not confuse the ViewModel here with the ViewModel of the MVVM pattern. They are not the same thing. The ViewModel in our case is instantiated by the controller. Often in my usage, the Business Model is passed to the ViewModel as a property. The reason not to pass the model directly to the view is not about seperating concerns, it is about being able to send View State data in addition to business data to the view. The view is not capable of directly modifying the business state since it is an out of band relationship. So, in this case passing the model to the view does not violate the separation of concerns, there is not cross dependancy here.
Secondly: should view model know about the business model? It looks definitely cleaner when CustomerViewModel holds its customer-related data in a Customer-type property, but on the other hand it's an extra dependency, which I should try to avoid. What's the preffered way of doing things?
Again, the ViewMOdel in the ASP MVC pattern is just a data model, that is all. It contains the View State and the Business State. In your example, the ViewModel should only know about the state of the Customer, not the business logic that determined the state. If you want to display busiess state, then you have to have that business state, the the passing of the business model. The business model passed to the view is not a reference value thus no dependancy.
Thirdly: is it okay to reuse a view model across many views? I've read here and there that every single view should have its own separate view model, but sometimes it's just tedious and makes the project messy imho.
Every Single View having its own separate view model is a rule of the MVVM pattern, not the MVC Pattern. In our ASP MVC pattern the ViewModel can be passed to any view that the controller is managing, it is only a model containing business and view state. In fact that is how many view or business state changes are passed to Controller Actions, through the ViewModel. A customer controller is concerned with the state of a customer, and that state should be relevant to all of the views that the customer controller is managing. So yes, in our MVC environment, reusing a ViewModel makes perfect sense.
Lastly: is implementing logic in views always wrong? Let's say I've got a list of customers and want to display a message "there are no customers registered" when it's empty. Is it necessary to implement it via view model (e.g. creating additional property "Message") or maybe a simple 'if' statement in a view wouldn't hurt?
Logic specific to the behavior/state of the View is naturally done within the context of the view. But in your case, the message that you are referring to is subject to the business state. The business state will know if the user is English or Arabic speaking because the language selection would be passed to the controller who would then repopulate the ViewModel with the correct text for the language chosen. This is usually kept in a resource file on the server. Even if you are only serving up English, text messages like your sample should be kept in an English resource file where they can be managed in one place. Consider the same message used in multiple places...do you want to go chasing them down when an edit is needed???
Oops, my soapbox Just broke and I fell off of it. what I have said here comes from many years experience implementing the MVC pattern and managing the separation of concerns. This is almost a religious topic for many. Know the rules, and if you must, bend them for your needs if you understand the consequences...happy coding