How to Use ViewModels Without Sacrificing Encapsulation

I have been using ASP.NET MVC extensively over the past year, and the more I use it, the more I like it. However, there remain a couple of things that bug me. One is the fact that the built-in validation doesn’t work with repeating forms. The other is the “best practice” of placing Data Annotations on a ViewModel class.

For me, validation rules belong on the business object itself, not on the ViewModel. One of the key benefits of encapsulation is that we reduce code duplication. If we don’t encapsulate the validation rules inside the object, then we are doomed to repeat them once for every presentation layer. Data Annotations in an MVC ViewModel are not available to a WPF UI. Not only does this lead to redundancy, it increases the risk of inconsistencies cropping up between UI.

So no problem, you might think. All we have to do is add the Data Annotations to the Model itself, and then add the Model as a property of the ViewModel.

Okay, let’s try that.

Here is the Model:

BasicClass simple C# class

And here is the ViewModel:

The ViewModel class

This looks straightforward enough. But look at what happens when we ask Visual Studio to scaffold the View:

View scaffolding

What happened to our “Basic” Model property? It’s not there. The scaffolding only seems to work for simple properties.

Okay, so let’s add the details of the Model to the View. In fact, let’s cheat. We’ll get Visual Studio to scaffold the inner Model for us. First we’ll create a throwaway View. Then we copy the contents of the form and paste it into the View that’s typed to the ViewModel. All we have to do then is change the lambda expressions to point at model.Basic rather than just model:

Full scaffolding

Problem solved. The View now contains the data we need and also respects our data annotations…

This means we can pass the ViewModel through to a Controller method and pick up the Model we need via the ViewModel’s “Basic” property. There’s only one problem:  How do we use the UpdateModel() method when we’re only interested in a property on the object passed to the method, rather than the whole object? Fortunately, Microsoft anticipated the need and there’s an overload on UpdateModel() that allows us to specify a prefix. In this case, not surprisingly, the HTML helpers have inserted the prefix “Basic”:

UpdateModel() with second argument

As you can see, the Model has successfully been bound, so we now have a mechanism for taking advantage of ViewModels without sacrificing encapsulation.

Kevin Rattan

For related information, check out Building Web Applications with ASP.NET MVC from Learning Tree.

Type to search

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.