ASP.NET MVC comes with a Models folder but no Model. Although some see this as a shortcoming, I'm actually delighted that the framework does not bind me to a specific data technology or pattern. If I want to use Active Record I can use Castle's ActiveRecord. If I want to use a Repository Pattern, I can use NHibernate. If I want to throw something together for a quick prototype, I can use Linq 2 Sql. The advantage of not being tied to a specific data access pattern for me is a win situation.
In many a demo, it's been indicated that the "Models" folder contains your model, whatever that happens to be. It could be your Domain Model, your L2S entities, etc. Now there are obvious reasons that whatever model you have, you wouldn't include it into your ASP.NET MVC application directly. You would probably reference it as an external assembly, and not directly place it in the Models folder.
So this begs the question. Do we just remove the Models folder? Well before I answer that, let me dig into something else.
Binding in ASP.NET MVC
We've seen many demos and tutorials where our model is directly passed in into our actions. We would have something along the lines of:
ASP.NET MVC's binding is pretty powerful. It can reflect on the properties of your class (even if they contain complex types) and match these up to the properties that come through over the wire, via the request POST. As long as you name the properties the same, it works like a charm. One issue that this introduces, as outlined by Justine in his post, as well as many others, is that the binding can come back to bite you. If you Customer entity has a field that you don't want the user to be able to update, you'll need to explicitly specify this by using attributes:
However, as simple as it might seem, it's error prone and violates DRY. Alternatives to this approach include creating custom model binders or using interfaces to specify the properties that you want to be databound. But let's hold that thought for a moment.
A typical update scenario for a typical entity
The following screen has a sample form to fill in the details for a customer
It's pretty standard. A bunch of fields and some dropdowns. But how is the dropdown values set? You could set them in the controller action just before displaying the view, using ViewData:
Now I don't know about you, but for me, using ViewData is a smell. If we don't use ViewData to pass information about our model, why should we be using it to pass information that our model indirectly consumes? And of course, being a dictionary that it is, it's prone to errors.
One plus one makes habitants for Models folder
We have two problems to solve:
- Binding to only those properties that we need
- Passing additional information to our views in a strongly-typed manner
Well this just cries out for a new class to encapsulate this information, i.e. a view model. Instead of binding directly to entities, you can bind to a new class that exposes only the information that is allowed to be updated. You can also use this class to provide other information required for a particular view. In the case of Customer, we could end up with something along the lines of:
In this case, we are using CustomerData as a DTO to hold the customer data (Name, Email, etc.) and the CustomerCreateViewModel as the View Model to hold other pertinent information for that particular view, for instance a list of countries. The action would now pass in this model as opposed to Customer:
We now have a strongly-typed model to represent all the information we need for a particular view, and since it pertains to the current MVC application and specific Views, what better place to hold this than the Models folder. Obviously based on your needs, you could provide a flattened version of this ViewModel but it does provide a cleaner approach to separate the actual DTO of your entity from the surrounding auxiliary requirements for a view.
Note: you need to make sure that you always provide a default parameter-less constructor for your view models since the framework requires this on binding.
By using strongly-typed views, you get the best of all worlds. You are able to make use of the binding provided by the MVC framework and it also provides a clean approach to providing specific data for views. And if that still doesn't cut it for you, think that you're making a home out of your Models folder!