tags:

views:

931

answers:

2

Does it make sense create an object that contains only those properties that the user will input on the webpage, use that for binding in the controller, and then map to the full Entity Object? Or should you just use the entity object, and use Include and Exclude to make restrictions on what gets bound on input?

+6  A: 

I have come to like the idea of using interfaces to segregate which properties should be included when the object is updated.

For example:

To create and update an person object:

interface ICreatePerson
{
  string Name { get; set; }
  string Sex { get; set; }
  int Age { get; set; }
}

interface IUpdatePerson 
{
  string Name { get; set; }
}

class Person : ICreatePerson, IUpdatePerson
{
  public int Id { get; }
  public string Name { get; set; }
  public string Sex { get; set; }
  public int Age { get; set; }
}

Then, when binding model, just use the appropriate interface as the type and it will only update the name property.

Here is an example controller method:

public ActionResult Edit(int id, FormCollection collection)
{
    // Get orig person from db
    var person = this.personService.Get(id);

    try
    {
        // Update person from web form
        UpdateModel<IUpdatePerson>(person);

        // Save person to db
        this.personService.Update(person);

        return RedirectToAction("Index");
    }
    catch
    {
        ModelState.AddModelErrors((person.GetRuleViolations());

        return View(person);
    }
}

See this article (and the comments) for a very good discussion of the options.

Steven Lyons
so in the ActionResult method you first accept the entire 'person' in the method parameter, and then filter with updatemodel?
zsharp
Generally, no. The UpdateMethod will use the form values behind the scenes. Given the limited space in the comments, I've updated the answer with an example method.
Steven Lyons
You can also pass the FormCollection to UpdateModel(), which will allow for unit testing without mocking.
Steven Lyons
+2  A: 

I recommend using a separate presentation model type in most cases. Aside from the issue of binding (which is important, but there are other ways around this issue), I think that there are other reasons why using presentation model types is a good idea:

  • Presentation Models allow "view-first" development. Create a view and a presentation model at the same time. Get your user representative to give you feedback on the view. Iterate until you're both happy. Finally, solve the problem of mapping this back to the "real" model.
  • Presentation Models remove dependencies that the "real" model might have, allowing easier unit testing of controllers.
  • Presentation Models will have the same "shape" as the view itself. So you don't have to write code in the view to deal with navigating into "detail objects" and the like.
  • Some models cannot be used in an action result. For example, an object graph which contains cycles cannot be serialized to JSON.
Craig Stuntz
actually, i want to do this but where do i define these classes? how exactly to implement? does the model binder bind these classes ?
zsharp
I put them in the Models folder of the MVC application. The "real" model (my Entity Framework model) goes in a separate assembly. Yes, the model binder can bind to these types. Sometimes the model the user POSTs is the same as the Presentation Model, sometimes not.
Craig Stuntz