Josh M.
Josh M.

Reputation: 27811

Change form context to ensure nested models are named correctly?

In RoR, you can change the form context so that it properly builds the form element ids and names (e.g. simple_fields_for myModel do |innerModel|, or similar). I'm wondering what's the correct way to do this w/MVC5. For example...

Models

class Model1 {
    public Model2 M2 { get; set; }
}

class Model2 {
    public List<Model3> M3s { get; set; }
}

class Model3 {
    public string Name { get; set; }
}

Controller

class MyController {
    public ActionResult Test(Model1 model) {
        View(model);
    }
}

View

@model Model1

@using (MvcForm form = Html.BeginForm()) {
    Html.RenderPartial("_Model2", this.Model.M2);
}

If 3 Model3 instances are posted back, the model state should be similar to:

M2.M3s[0].Name=Name1
M2.M3s[1].Name=Name2
M2.M3s[2].Name=Name3

In this case, the view is using a partial to render Model2, but the partial doesn't know that it's in the context of this.Model.M2 and therefore does not prefix the ids and names generated with Model2. -- it simply starts them with Model3. The solution would be to use a new form context (not literally meaning FormContext), something like this:

@using (MvcForm form = Html.BeginForm()) {
    using (form.For(m => m.M2)) {
        Html.RenderPartial("_Model2", this.Model.M2);
    }
}

Note that form.For does not exist, but the intention is that it changes the current ModelMetadata to have the appropriate context and prefix of M2. Thus, anything rendered within that block would inherit that new context and the ids and names would be correctly generated.

Upvotes: 3

Views: 267

Answers (1)

Mathew Thompson
Mathew Thompson

Reputation: 56439

You can actually specify the prefix when you call RenderPartial, then the form values of your partial view fields will automatically receive that prefix:

Html.RenderPartial("_Model2", this.Model.M2, new ViewDataDictionary
{
    TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "M2" }
})

Upvotes: 2

Related Questions