-1

Building a form that allows user to add infinite lines. This is done with ajax call to controller that adds a partial view (one time per click).

I am using Html.BeginCollectionItem to index each input in the partial views.

I can add a bunch of items and click submit, I can see the form is posted in fiddler, but the controller shows a null form. If I change the post controller type from List<> to singular AccessoryVM, I get the first item.

I have tried swaping the model type in the Index view from List to IEnumerable, no change.

Index:

@model List<EmployeeHardwareRequest.Models.ViewModels.AccessoryVM>

@{
    ViewBag.Title = "Select Accessories";
}

<h2>Accessories</h2>


    @using (Html.BeginForm("Index", "Accessory", FormMethod.Post, new { @class = "form-horizontal" }))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div id="form-body">
            @foreach (var item in Model)
            {
                @Html.Partial("_NewItem")
            }
        </div>

        <div class="row">
            <div class="col-md-6">
                <button id="add-item" class="btn btn-primary">Add Another Item</button>
            </div>
            <div class="col-md-6">
                <input type="submit" value="Select Software" class="btn btn-default pull-right" />
            </div>
        </div>
    }

Partial:

@model EmployeeHardwareRequest.Models.ViewModels.AccessoryVM

<div class="form-group col-md-3">
    <div>
        @Html.DropDownListFor(model => model.SelectedAccessory, Model.AccessoryDdl, new { @class = "form-control accessoryList" })
    </div>
</div>

<div class="form-group col-md-8">
    <div>
        @using (Html.BeginCollectionItem("AccessoryVM"))
        {
            @Html.EditorFor(model => model.ProductLink, new { htmlAttributes = new { @class = "form-control", @placeholder = "Enter link to web page" } })
            @Html.ValidationMessageFor(model => model.ProductLink, "", new { @class = "text-danger" })
        }
    </div>
</div>
<div class="col-md-1">
    <button type="button" id="deleteItem" class="btn btn-danger">
        <span class="glyphicon glyphicon-remove"></span>
    </button>
</div>

Controllers: Index: public ActionResult Index() { List modelList = new List();

        List<Accessory> accessories = _db.Accessory.ToList();  // change this to use the accessoryDTO

        List<int> monitorSizeList = new List<int>  // replace this with data from db table.
        {
            20, 22, 24, 27
        };

        model.AccessoryDdl = new SelectList(accessories, "AccessoryId", "ItemDescription", selectedAcc);
        model.MonitorSizeDdl = new SelectList(monitorSizeList);
        return View(modelList);
    }

Get partial view:

    public ActionResult AddItem(int index)
    {
        AccessoryVM model = new AccessoryVM();
        int selectedAcc = 1;

        List<Accessory> accessories = _db.Accessory.ToList();  // change this to use the accessoryDTO

        List<int> monitorSizeList = new List<int>  // replace this with data from db table.
        {
            20, 22, 24, 27
        };

        //model.lineIndex = index++;

        model.AccessoryDdl = new SelectList(accessories, "AccessoryId", "ItemDescription", selectedAcc);
        model.MonitorSizeDdl = new SelectList(monitorSizeList, "Select Monitor Size");
        return PartialView("_NewItem", model);
    }

post:

    [HttpPost]
    public ActionResult Index(List<AccessoryVM> form)
    {

I have checked for double use of keywords and properties, but don't see any conflicts.

BattlFrog
  • 3,370
  • 8
  • 56
  • 86
  • Basically, the problem is that at submit you are submitting List which excepts the model binding name as [0].SelectedAccessory, [0].ProductLink, [1].SelectedAccessory, [1].ProductLink....................... However, the partial view generates same name SelectedAccessory and ProductLink for each row. This breaks the model binding. To fix it, either you can create a list at js to push data from each row and post it to server or generate the input control name in partial view as required for model binding. – user1672994 Dec 23 '15 at 03:53

1 Answers1

0

You can Use this in your post function

 [HttpPost]
 public ActionResult Index(List<AccessoryVM> form)
 {
    foreach (var AccessoryVM in model.AccessoryVMs)
    {
       //do stuff with each of these here ..
    }
  }

Regards Jasbeer Singh