0

I have a details page which lets me edit the information associated with a particular item.

    public ActionResult Details(int id)
    {
        Call call = db.Calls.Find(id);
        return View(new CallFormViewModel(call));
    }

I use a view model --

public class CallFormViewModel
{
    public Call     Call    { get; private set; }

    public CallFormViewModel()
    {
        Call = new Call();
    }

    public CallFormViewModel(Call call)
    {
        Call = call;
    }
 }

When I submit, I want to only allow certain properties of the 'call' object to be updated. My Post handling method looks like this -

    [HttpPost]
    public ActionResult Details(CallFormViewModel callForm)
    {

         (some code removed for clarity)

         UpdateModel(callForm.Call ,new string[] {
            "Contact",
            "Summary",
            "Description",
        }

    }

The problem is that callForm has already been updated with all of the input from the form submit before I even call UpdateModel.

How can I change this and use UpdateModel to selectively update fields?

Thanks

Edit:

I think i've been looking at this the wrong way. What I should be doing is this:

    [HttpPost]
    public ActionResult Details(int id, CallFormViewModel callForm)
    {

         var call = db.Calls.Find(id);

         (some code removed for clarity)

         UpdateModel(call, "Call", new string[] {
            "Contact",
            "Summary",
            "Description",
        }

    }

This way it's taking the incomplete data [and only the fields i want] and applying it to the actual model. I had been confusing the callForm.Call with the actual model object, when infact it's only a representation of it.

Have to wait till I get to work to test this theory.

1
  • You better use AutoMapper to switch from Entity to the ViewModel. The ViewModel should be the only "data" you use and manipulate until you want to save\Edit then you switch to the real Entity which you save. AutoMapper helps separate the ViewModel from the Entity. Hope this tip help you a lot in the very close future. Commented Jan 9, 2012 at 8:37

2 Answers 2

2

When you write your ViewModel in the Action parameters, The Model Binder Bind the ViewModel properties to the "incoming" data. This should work:

[HttpPost]
public ActionResult Details()
{
    CallFormViewModel callForm = new CallFormViewModel();

     UpdateModel(callForm.Call ,new string[] {
        "Contact",
        "Summary",
        "Description",
    }
}

Update:

The Bind attribute option:

[Bind(Include = "Contact,Summary,Description")]
public class CallFormViewModel
{
    // As before...
}
Sign up to request clarification or add additional context in comments.

7 Comments

How is the callForm being constructed?
@NoPyGod, I'm not sure it's must be constructed before, but you can "new" it. I updated.
And if there are also properties on the CallFormViewModel itself which are relevant, should I do this UpdateModel(callForm, new string[] {"something", "somethingelse", "call.contact", "call.summary"}) ? It seems like some pretty heinous code when I start doing things like this.
@NoPyGod, You can use the Bind Attribute Which is nicer and tidy.
what am i using it on exactly?
|
0

You don't need to call UpdateModel because you will get an updated model passed as the parameter to your method. If you'd prefer to use UpdateModel, you should remove the parameter from the action method.

To then update just the fields you are interested in, you should either:

  1. Have the method take a different view model that only includes the fields that should be updated.
  2. Change the form so that only the fields you want updated are in text boxes (or other updatable controls) created by the HTML.TextBoxFor() methods.

1 Comment

The second option you wrote is dangerous. There could be a malious user sending his data like- ?discount=100% or ?manager=true. And the first option (IMO) is too complicated, having two view models for one Entity, Just use the Bind attribute.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.