2
votes

I'm trying to create asp mvc 3 page with a form with text fields that are dynamically generated based on the number of object in a list that is in the model I passed into page controller. The problem I'm running into is that whenever I post to the controller the list maintains the values but not the names of the objects in the list. Here is an example:

The Model:

public class SomeModel
    {
        List<Field> fieldList;
        public SomeeModel()
        {
            fieldList = new List<Field>();
        }


        public string Name { get; set; }

        public List<Field> FieldList
        {
            get
            {
                return fieldList;
            }
        }

    }

The controller:

public ActionResult Preview()
{
    SomeModel model = new SomeModel();
    model.FieldList.Add( new Field { name = "test 1"});
    model.FieldList.Add( new Field { name = "test 2"});
    model.FieldList.Add( new Field { name = "test 3"});

    return View(model);
}

The View:

@using (Html.BeginForm()) {
    <div>
        <fieldset>
            <legend>Input Field List</legend>

            @for (var i = 0; i < Model.FieldList.Count(); i++)
            {
                <div class="editor-label">
                   @Html.Label(Model.FieldList[i].name)
               </div>
               <div class="editor-field">
                   @Html.TextBoxFor(model => Model.FieldList[i].value)
               </div>
            }

             <p>
                <input type="submit" value="Generate PDF" />
            </p>
        </fieldset>
    </div>

I saw a similar post here .NET MVC Razor Dynamic Form Generation but answer runs into the same issues as I got. Hope I'm being clear! If not I'll post more info. Thanks!

1

1 Answers

7
votes

You could include those names as hidden fields. This way their values will be posted to the controller action:

@for (var i = 0; i < Model.FieldList.Count(); i++)
{    
    @Html.HiddenFor(model => Model.FieldList[i].name)
    ...
}

Also instead of writing those loops I would recommend you using editor templates:

@model SomeModel
@using (Html.BeginForm()) 
{
    <div>
        <fieldset>
            <legend>Input Field List</legend>
            @Html.EditorFor(x => x.FieldList)
            <p>
                <input type="submit" value="Generate PDF" />
            </p>
        </fieldset>
    </div>
}

and the corresponding editor template (~/Views/Shared/EditorTemplates/Field.cshtml) which will be rendered for each element of the FieldList collection:

@model Field
@Html.HiddenFor(model => model.name)
<div class="editor-label">
    @Html.LabelFor(model => model.value, Model.name)
</div>
<div class="editor-field">
    @Html.TextBoxFor(model => model.value)
</div>

Another possibility instead of using hidden fields would be to externalize those names into some data store and then have a repository which would return them. So in your two actions you would simply query this repository for the names. Because they cannot be changed it is not necessary to include them in the HTML.