I've struggled to find any discussion on this.
If you have a simple MVC page for updating a User, and you put a dropdown list on it of Country, you need to populate the dropdown list in the viewmodel. Let's call it List<Country> countries {get; set;}
If the page is posted, and there's an error like they forgot to put a User Name in, we redirect them to the page again to try again, at which point we also have to remember to repopulate the model's List<Country>
before redirecting them back to the page.
Three ways to handle this that I know of:
- In the controller, make a call to the database, e.g.
viewModel.Countries = _dataAccess.GetCountries()
- Store the list in the view bag and not in the model at all e.g.
ViewBag.Countries = _dataAccess.GetCountries()
- Put it into the view model itself, so that
List<Country> {get { return _dataAccess.GetCountries();
and thus inject in aDataAccess
object.
The third approach is what I am considering because then you don't need to worry about populating/repopulating the fields in the controller. But I can't find any evidence via searching that this is an acceptable method, so I fear there is a drawback I am not considering.
The third method also has a big problem in that GetCountries()
is async, and you can't call async methods in properties or even in constructors it seems.
Best Answer
I think this is the main difference between MVC and MVVM approaches.
In MVC you have the controller populates the ViewModel which is essentially just the a struct of the various data the view needs
In MVVM you don't have a controller, so all the logic goes in the ViewModel, which is now a 'proper' class with methods and everything.
If you are in the ASP MVC framework, then you are constrained by the fact that the view is a webpage running on a client machine. It can't really make calls back to the viewmodel generated server side. So you might as well do the logic in the controller.
There's no obvious harm in having the controller build a ViewModel, call its methods and return the results. But it's an extra step you don't need.
Say for example, you have the page with its server side populated list of countries, populated via viewModel.GetCountries()
But you also have a client side api call which returns the list of countries.
Would you choose in your controller to do
and
It doesn't make sense from the API to use the MVVM style because its just using a single property from the VM.
Further, you can't bind your client side commands to the server side VM. Its instanciated and discarded on every HTTP call.
The downside of the MVVM approach becomes apparent when you have a complex viewmodel and only want a small part of it to perform an action. ie.