Log in

MVC View Model constraints

From MDrivenWiki

I made a little MVC sample. I deliberately made it really small and simple – but made sure it shows create,delete and update of attributes and relations.

01 - VM constraints.png

I have added this sample to the Demos in the general download.

Three ViewModels:

  • One to act as index page
02 - VM constraints.png
  • one that shows Example1 and its connected Example2’s
03 - VM constraints.png
  • and one that show a single Example2
04 - VM constraints.png

Then I made 2 controllers, one for Example1 and one for Example2.

The main goal with using the model defined ViewModels is to use as little code as possible in the Views and in the Controllers. And also to make the code used predictable, simple and easy to maintain.

The patterns that emerges is sort of this:


        public ActionResult Details(string Identity)
          EcoProject1.Example2 e2 = this.EcoSpace.ExternalIds.ObjectForId(Identity).AsObject as EcoProject1.Example2;
          return View("Details",  VMExample2.Create(this.EcoSpace, e2));

Here we resolve an id to an object, then use the ViewModel as a façade on that object and send it to the view. The benefit is that I do not have to expose my whole business object to the view, and I can also do view specific derivations in the viewmodel.


        public ActionResult Details(string Identity, VMExample2 offlinevm)
          Example2 e2 = EcoSpace.ExternalIds.ObjectForId(Identity).AsObject as Example2;
            VMExample2 onlinevm=VMExample2.Create(EcoSpace, e2);
            ViewModelHelper.ApplyValues(offlinevm, onlinevm, null);
            return View("Details", onlinevm);
            return View("Details", offlinevm);

Here we resolve the id to an object, create an online viewmodel for that object, apply the values from the sent in offline viewmodel and commit. The benefits here are mainly that only the things in the viewmodel can change –protecting the rest of your business object. The viewmodel can also be a compilation of details from other parts of your model – and the view need not know anything about this. The viewmodel also has the ability to opt out the constraints from the seen classes that does not make sense in this view. This way class wide constraints can be used and filtered per view.


        public ActionResult Delete(string Identity)
          Example1 e1 = this.EcoSpace.ExternalIds.ObjectForId(Identity).AsObject as Example1;
          return View("Index", VMExample1Index.Create(this.EcoSpace, null));

Again, look up object from id, call the BusinessDelete that checks our delete constraints, then prepare a viewmodel for where we should end up afterwards. The benefits here are that constraints that are put in place to protect the information from ending up in any illegal state is effectively applied even if the update touches several objects.


        public ActionResult Create()
          Example1 x1 = new Example1(this.EcoSpace) { Attribute1="HoHoHo",Attribute2="HeHeHe"};
          return View("Index",VMExample1Index.Create(this.EcoSpace, null));

Just create the object and commit, skipping the Validate – since I do not know how to react to objects that break their constraints at birth…

The Views use the ViewModels and get code completion since the viewmodels has generated code:

@foreach (var item in Model.Example2) {
            @Html.DisplayFor(modelItem => item.Attribute1)
            @Html.ActionLink("Details & Edit", "DetailsForExample2", new {  Identity=item.Identity }) |
            @Html.ActionLink("Delete", "DeleteExample2", new { Identity=item.Identity })
Having the bulk of your logic and your rules in the model is a good thing. To help you maintain your model there are some new features that you will want to use:

1. The CheckModel checks all expressions – ViewModel columns and contraints and derived attributes and associations:

05 - VM constraints.png

2. There is a new CrossReference menu that works on all things in the model, Classes,Attributes and Associations. So you can easily see if an Attribute is in a ViewModel or used by an association etc:

06 - VM constraints.png