Jquery 部分视图中绑定动态表单元素-索引超出范围错误

Jquery 部分视图中绑定动态表单元素-索引超出范围错误,jquery,asp.net-mvc,partial-views,Jquery,Asp.net Mvc,Partial Views,我有一个MVC4应用程序,在razor视图上有一个表单。一个页面允许用户根据需要多次“添加另一个”。添加的行是局部视图,但不必如此。我使用添加的行数作为索引。在第一次尝试添加行时,我在部分视图中得到了错误。就我所知,索引值是0,所以不确定它为什么超出范围 对控制器的Ajax调用: $("#add-item").on("click", function () { var index = $('.accessoryRow').length; $.ajax({ url:

我有一个MVC4应用程序,在razor视图上有一个表单。一个页面允许用户根据需要多次“添加另一个”。添加的行是局部视图,但不必如此。我使用添加的行数作为索引。在第一次尝试添加行时,我在部分视图中得到了错误。就我所知,索引值是0,所以不确定它为什么超出范围

对控制器的Ajax调用:

$("#add-item").on("click", function () {
    var index = $('.accessoryRow').length;
    $.ajax({
        url: '/Accessory/AddItem',
        cache: false,
        data: { index: index },
        success: function (html) {
            $("#form-body").append(html);
        }
    });
    return false;
});
表格正文:

@using (Html.BeginForm("Index", "Accessory", FormMethod.Post, new { @class = "form-horizontal" }))
{
    @Html.AntiForgeryToken()

    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div id="form-body">

    </div>
}
@使用(Html.BeginForm(“Index”,“附件”,FormMethod.Post,new{@class=“form horizontal”}))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true,“,new{@class=“text danger”})
}
局部视图:

@model EmployeeHardwareRequest.Models.ViewModels.AccessoryVM

@{
        var i = Model.lineIndex;
    }

<div class="accessoryRow">
    <div class="form-group col-md-3">
        @*@Html.LabelFor(model => model.ItemDescription, htmlAttributes: new { @class = "control-label" })*@
        <div>
            @Html.DropDownListFor(model => model.Accessories[i].AccessoryId, Model.AccessoryDdl, new { @class = "form-control accessoryList" })
        </div>
    </div>

    <div class="form-group col-md-8">
        @*@Html.LabelFor(model => model.ProductLink, htmlAttributes: new { @class = "control-label" })*@
        <div>
            @Html.TextBoxFor(model => model.RequestedAccessories[i].ProductLink, new { htmlAttributes = new { @class = "form-control", @placeholder = "Enter link to web page" } })
            @Html.ValidationMessageFor(model => model.RequestedAccessory.ProductLink, "", new { @class = "text-danger" })


            @*@using (Html.BeginCollectionItem("AccessoryVM"))
                {
                    @Html.EditorFor(model => model.RequestedAccessory.ProductLink, new { htmlAttributes = new { @class = "form-control", @placeholder = "Enter link to web page" } })
                    @Html.ValidationMessageFor(model => model.RequestedAccessory.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>
</div>
@model EmployeeHardwareRequest.Models.ViewModels.AccessoryVM
@{
var i=Model.lineIndex;
}
@*@LabelFor(model=>model.itemsdescription,htmlAttributes:new{@class=“control label”})*@
@Html.DropDownListFor(model=>model.accessorid[i].AccessoryId,model.accessorydll,new{@class=“form control accessoryList”})
@*@LabelFor(model=>model.ProductLink,htmlAttributes:new{@class=“control label”})*@
@Html.TextBoxFor(model=>model.RequestedAccessories[i].ProductLink,新的{htmlAttributes=new{@class=“form control”,@placeholder=“Enter link to web page”})
@Html.ValidationMessageFor(model=>model.RequestedAccessory.ProductLink,“,新的{@class=“text danger”})
@*@使用(Html.BeginCollectionItem(“AccessoryVM”))
{
@EditorFor(model=>model.RequestedAccessory.ProductLink,new{htmlAttributes=new{@class=“form control”,@placeholder=“Enter link to web page”})
@Html.ValidationMessageFor(model=>model.RequestedAccessory.ProductLink,“,新的{@class=“text danger”})
}*@
提供部分服务的控制器:

    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);
    }
public ActionResult AddItem(int索引)
{
AccessoryVM模型=新AccessoryVM();
int-selectedAcc=1;
List accessories=\u db.accessority.ToList();//将此更改为使用accessoryDTO
List monitorSizeList=新列表//将其替换为db表中的数据。
{
20, 22, 24, 27
};
model.lineIndex=索引;
model.accessorydll=新选择列表(附件,“AccessoryId”、“ItemDescription”、selectedAcc);
model.MonitorSizeDdl=新选择列表(monitorSizeList,“选择监视器大小”);
返回PartialView(“\u NewItem”,model);
}
因此,理论是,单击按钮添加一行,ajax函数读取行数,将该索引传递给控制器,控制器将其添加到模型中,并发送到分部,在分部中集成到html中,用于模型绑定。行被添加,如果再次单击add按钮,循环将再次开始,但由于添加了行,这次索引为1


老实说,我不在乎我如何实现这个目标(在合理的范围内,我不会放弃一切,使用不同的技术)。如果在MVC中有一种“标准”的方法可以做到这一点,我就找不到了。

在您的
AddItem
控制器操作中,您似乎没有填充视图模型的
RequestedAccessories
Accessories
属性,但在视图中您试图访问它们:

@Html.DropDownListFor(model => model.Accessories[i].AccessoryId, Model.AccessoryDdl, new { @class = "form-control accessoryList" })
在这里:

@Html.TextBoxFor(model => model.RequestedAccessories[i].ProductLink, new { htmlAttributes = new { @class = "form-control", @placeholder = "Enter link to web page" } })
所以,如果希望访问这些集合,请确保已使用相应的元素填充这些集合


顺便说一句,在这种情况下,更好的方法是使用非顺序索引,如中所示。这使得动态添加元素变得更加容易。您也可以检查这一点,这将使它更容易。

感谢Darin的快速响应。下拉列表填充在控制器中,但我不确定填充RequsestedAccessories集合时您指的是什么,因为没有任何东西可以填充它。我是不是遗漏了一个概念?你说没有什么东西可以填充它是什么意思?如果视图中没有任何元素,您希望如何通过索引访问该集合?您应该使用用户到目前为止已经添加的元素填充此集合,并在其中添加一个空元素,该元素将表示新添加的行。但我强烈建议你阅读我在回答中提到的博客文章,找到一种更简单、更好的方法来实现这一点,谢谢你的链接。我试过史蒂夫的方法,但总是得到一个答案“foreach中的模型引用出现null对象错误,我假设这是显示的过程,而不是输入new,因为如果表单尚未填写,模型中当然没有任何内容。但是,我觉得我在这里遗漏了一些基本概念。。。。由于表单尚未填写,因此没有“用户迄今为止添加的内容…”在这种情况下,请确保在尝试呈现任何输入元素和访问集合之前,已在视图中测试了
i>0
。显然,这只在第一次没有添加元素时才起作用。当您随后调用
AddItem
操作时,您将需要填充集合,正如我在回答中已经解释的那样。