views:

42

answers:

1

Hi I have a question about model binding. Imagine you have an existing database entity displayed in a form and you'd like to edit some details, some properties eg createddate etc are not bound to the form, during model binding, these properties are not assigned to the model as they are not on the http post data or querystrong etc, hence their properties are null. In my controller method for update , Id just like to do

public ActionResult Update( Entity ent) { //Save changes to db }

but as some properties are null in ent, they override the existing database fields which are not part of the form post data, What is the correct way to handle this? Ive tried hidden fields to hold the data, but model binding does not seem to assign hidden fields to the model. Any suggestions would be appreciated

+1  A: 

You shouldn't be sending your entity to your view, you should send a slim version of it called a DTO (data transfer object) or ViewModel.

Only send the properties to the view (and hence the form that gets posted back) that you want the user to update with that action.

In your POST handler you can then validate and copy the properties across to your entity.

an AutoMapper can help if you have lots of properties

something like:

public class User
{
    int id;
    string name;
    string email;
}

public class EditUserEmailDto
{
    string email;
}

// get
public ActionResult EditEmail(int id,)
{
    return View("EditEmail", new EditUserEmailDto());
}    

// post
public ActionResult EditEmail(int id, EditUserEmailDto dto)
{
    if(!ModelState.IsValid)
        return View("EditEmail", dto);

    var user = userRepo.Get(id);
    user.email = dto.email;
    userRepo.Save(user);

    return;
}
Andrew Bullock
That makes sense Andrew, thanks for your reply. I think your solution works in a simple scenario, how about when you are utilising a custom model binder that works for both save and update scenarios and needs to assign values to a type as opposed to viewdata. How would you handle this?
mctayl
And also how would you make use of features like model validation etc?
mctayl
re 1st comment: not sure i get what you mean, can you explain the problem? re 2nd comment, i do my validation in the binder, this way it keeps the post handler tidy. ill update the answer to show an example of the handler, but the validation bit may be overkill here. basically i extend `DefaultModelBinder`, override `BindModel`, call `base.BindModel` then get a validator from my IoC Container for the model type, validate the model, then stick any errors in the `ModelState`
Andrew Bullock