MVC如何动态地将输入字段添加到视图模型

时间:2015-10-29 17:19:16

标签: c# jquery ajax asp.net-mvc-4 razor

您好我有一个使用以下viewmodel

的表单
    public class MainViewModel
    {
        public int Id { get; set; }

        public List<LotViewModel> Lots { get; set; }

        [DisplayName("Number of Lots")]
        public int NumberOfFields { get; set; }
    }

NumberOfFields在for循环中用于渲染LotViewModels。用户从1 - >中选择一个数字。 4从下拉。然后有一个JS函数使用AJAX调用Controller方法来呈现包含正确数量的字段的局部视图。下拉列表更改时会触发此JS函数。

这是控制器方法

[HttpPost]
public PartialViewResult AddLotFields(int numberOfFields)
{
    var viewModel = new MainViewModel
    {
        Lots = new List<LotViewModel>(),
        NumberOfFields = numberOfFields
    };
    return PartialView("~/Areas/Admin/Views/MainController/_LotForm.cshtml", viewModel);
}

这是Javascript

$(function() {
$("#numberOfLotsDD").change(function(event) {
    $.ajax({
        url: window.g_baseUrl + "MainController/AddLotFields/",
        data: {
            numberOfFields: $(this).val()
        },
        cache: false,
        type: "POST",
        dataType: "html",

        success: function(data, textStatus, XMLHttpRequest) {
            $("#LotFields").html(data);
        }
    });
});
});

这很好但是当你提交表单时,viewModel不包含任何元素。

呈现输入字段的部分视图是

@model MainViewModel

@for (var i = 0; i < Model.NumberOfFields; i++)
{
    Model.Lots.Add(new LotViewModel());
    <div class="row">
        <div class="col-md-6">
            <div class="form-group ">
                @Html.LabelFor(model => model.Lots.Last().BatchIdLocation)
                @Html.TextBoxFor(model => model.Lots.Last().BatchIdLocation, new { @class = "form-control", @placeholder = "Enter Batch Id tag" })
                @Html.ValidationMessageFor(model => model.Lots.Last().BatchIdLocation)
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group ">
                @Html.LabelFor(model => Model.Lots.Last().QuantityLocation)
                @Html.TextBoxFor(model => Model.Lots.Last().QuantityLocation, new { @class = "form-control", @placeholder = "Enter Quantity tag" })
                @Html.ValidationMessageFor(model => Model.Lots.Last().QuantityLocation)
            </div>
        </div>  
    </div>
}

我已经搞砸了几种尝试保存这种形式的方法,但没有一种方法有效。

我知道如果我真的卡住了我可以使用JQuery将表单输入值发送到我的控制器。但我想尽可能避免这种情况,并将解决方案局限于c#和razor

2 个答案:

答案 0 :(得分:1)

您的字段名称必须采用Lots[N].PropertyName的格式,但您的字段名称仅生成为PropertyName

不使用model.Lots.Last(),而是使用实际索引,即model.Lots[i]

答案 1 :(得分:1)

建议 - 您可以在服务器端itselft中创建集合中的项目,而不是传递标记以查看以生成多个项目。

[HttpPost]
public PartialViewResult AddLotFields(int numberOfFields)
{
    var lots = new List<LotViewModel>();
    for (int index = 0; index < numberOfFields; index++)
    {
        lots.Add(new LotViewModel());
    }

    return PartialView("~/Areas/Admin/Views/MainController/_LotForm.cshtml", lots);
}

这也使您能够使用外部因子相关值初始化视图模型属性。

因此视图中的更改如下:

@model List<LotViewModel>

@for (var i = 0; i < Model.Count; i++)
{
    <div class="row">
        <div class="col-md-6">
            <div class="form-group ">
                @Html.LabelFor(model => model.Lots[i].BatchIdLocation)
                @Html.TextBoxFor(model => model.Lots[i].BatchIdLocation, new { @class = "form-control", @placeholder = "Enter Batch Id tag" })
                @Html.ValidationMessageFor(model => model.Lots[i].BatchIdLocation)
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group ">
                @Html.LabelFor(model => model.Lots[i].QuantityLocation)
                @Html.TextBoxFor(model => model.Lots[i].QuantityLocation, new { @class = "form-control", @placeholder = "Enter Quantity tag" })
                @Html.ValidationMessageFor(model => model.Lots[i].QuantityLocation)
            </div>
        </div>  
    </div>
}

上述更改还将在html中为每个字段创建相应的名称,以便在表单发布时,数据适当发布。