Models for a view (some objects are more equal than others)

How to implement the V and the C in MVC is no point of great discussion. When it comes to the M the variation increases. An ASP.NET MVC app has a Models folder; what you will find in there varies among the many samples found. The folder looks a bit like a dumping place for the author’s favorite technology, be it EF, sql data adapters, web-services, domain objects, pure agnostic view models or whatever else comes into imagination.

In this post I will explore a little bit what kind of models to use. In case you consider the only just solution a pure view model, as presented in MVVM (model View ViewModel), you do have a valid best practice. Read on nevertheless for reasons why that’s good. Models based explicitly on an technology like ado.net are a bad practice, that is beyond discussion. Left in the middle are things like domain-objects. Mapped (FI) by nHibernate to a sql database and served to your app through repositories. To your app these objects are plain objects (POCO’s), at first sight not hindered by any underlying technology. In a real app they do have some behavior, lazy loading being only one aspect of that, which might fire back.

Can you use such a mapped domain object in a View ? As said, the best practice is to wrap up the object in a ViewModel. With a different model for every view. In real life not everybody does that. It can be tedious and a maintenance nightmare. In quite a number of cases we do use domain objects in our views. Which does work provided you treat them with care.

When presenting data lazy loading sticks up it’s head. It will fire when the view is actually rendered. Which happens after the controller action has completed. As long as the session to the database is still available that will work. I spent my last post on that.

When updating a domain object from posted data real danger emerges. I’ve seen very poisonous recipes (pun again intended) doing that. They boil down to the following snippet. There is a DO Patient, in the view a patient’s data has been edited and is now posted back to the controller to be persisted to the database.

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Patient(Patient patient)

{

    Repository.Persist(patient);

    return PartialView(patient);

}

What will happen is that the MVC routing will find a match for the controller action. It will create a new patient object and populate that with the form’s data. Also when the data belonged to a existing patient. The original sample contained some fiddling to try to restore that. But that should not be the way, deep down below you are messing with nHibernates’s deep inner workings. Something you would rather stay on good terms with.

There is a neat way out. Change your action to the following

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Patient(int patientId, FormCollection form)

{

    var patient = patientId == 0 ? Repository.New() : Repository.Get(patientId);

    TryUpdateModel(patient);

    Repository.Persist(patient);

    return PartialView();

}

The controller is now “aware” of an identifying Id of the DO. Which is going to be part of the route parameters of the form

using (Ajax.BeginForm(“Patient”, “Patient”, new { patientId = Model.Id }, new AjaxOptions { UpdateTargetId = “patientnaw” }))

        {

When posting back the routing will hit our action. Which now has the Id to get the (new) patient’s data from the repository. TryUpdateModel then updates the patient from the posted back formdata in the second parameter, after which the patient can be persisted. In your real app you should of course check the result of TryUpdateModel and do some real validation. For now that is beyond the scope of this post.

What should be clear is that it is a one way street, the DO’s can flow from controller to the view, but don’t ever expect the view to post back a real DO. Whether to work with only pure, really agnostic, ViewModels or nevertheless to use DO’s straight from the repository is up to you. I hope to have shown you some of the pitfalls, and a way out, of doing the latter.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.key-logger.ws/ key logger download

    This Is Very interesting .. thanks for sharing this post

  • Miniscalope

    Really nice but i have this dillema after reading your post :(

  • Anonymous

    I meant as I wrote it :)
    Any post with an idPatient in the form values will route to this action. TryUpdateModel will update the patient (coming from the repository) with matching fields in the form field collection.

  • Derek Woolverton

    Just for my understanding, did you mean TryUpdateModel(patient); or TryUpdateModel(form);  Just trying to follow where form routes to.

  • Steve Py

    One of the focal points I have with MVVM is that my view-model may be aware of the model, but the view never binds directly to a model. The main reason for this is so that the VM is responsible for exposing models the way a view should be consuming them, and regulating what the view can edit before any change to a model is persisted. 
    So yeah, where I support one VM per View, in MVC I will lean more towards a (v)MVC-like pattern and ensure one (v)M per View where a (v)M wraps one or more Models.

  • JJ

    I agree with Nick, the controller has too much responsibility.  The decision whether to update or create should be made further down the stack.

  • http://twitter.com/ntcoding Nick

    On the right tracks with not posting domain entities. I don’t believe you want that logic in the controller and I’m certain you want to avoid TryUpdateModel – which isn’t good for testing.

    Have a look at FubuMVC’s One Model In One Model Out Philosophy.