Rachel
Rachel

Reputation: 132618

Why does creating a new ViewModel return the same data as the old ViewModel?

I'm just learning MVC3 now and this is really confusing me.

I have a ViewModel that contains some child ViewModels. Each of the ChildViewModels get rendered with a different Partial View, and when submitting execute a different action on the Controller. All the ChildViewModels should perform some custom validation on their data, and if successful it should move on to the next page. If the validation fails, it should simply return to the ParentView and display the errors.

[HandleError]
public class MyController: Controller
{
    public ActionResult Index()
    {
        var viewModel = new ParentViewModel();
        return View("ParentView", viewModel);
    }

    [HttpPost]
    public ActionResult ChildViewModelB_Action(ChildViewModelB viewModel)
    {
        if (ModelState.IsValid)
        {
            return View("ChildViewModelB_Page2", viewModel);
        }
        else
        {

            // I'm having trouble returning to the ParentView and
            // simply displaying the ChildViewModel's errors, however
            // discovered that creating a new copy of the VM and displaying 
            // the ParentView again shows the existing data and any errors
            // But why??
            var vm = new ParentViewModel();
            return View("ParentView", vm);
        }
    }
}

For example,

Why does creating a new copy of the ParentViewModel display the ParentView with the same data as the original ParentViewModel?

And is there a different way I should be returning to the ParentView after doing server-side validation?

Upvotes: 1

Views: 924

Answers (2)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039328

You need to clear the modelstate if you intend to modify values in your POST action

else
{
    ModelState.Clear();
    var vm = new ParentViewModel();
    return View("ParentView", vm);
}

The reason for that is because Html helper such as TextBoxFor will first look in the modelstate when binding their values and after that in the model. And since the modelstate already contains the POSTed values, that's what's used => the model is ignored. This is by design.

This being said the correct thing to do in your case is to simply redirect to the GET action which already blanks the model and respect the Redirect-After-Post pattern:

else
{
    return RedirectToAction("Index");
}

Upvotes: 2

VJAI
VJAI

Reputation: 32768

Why does creating a new copy of the ParentViewModel display the ParentView with the same data as the original ParentViewModel?

Because the values of the fields are retrieved from the POSTed form and not from the model. That makes sense right? We don't want the user to show a form filled with different values from what they submitted.

Upvotes: 0

Related Questions