使用 EF 动态添加的表单数据未绑定到回发 .net 框架 4.7.2 MCV

Dynamically added form data not binding on postback .net framework 4.7.2 MCV using EF

我有一个包含动态对象数组的模型。这个对象只有一个开始日期时间、结束日期时间和一个表示槽数的整数。

我正在使用 MVC、EF 和 .net 4.7.2

我最终想做的是允许用户(使用js)将多条记录添加到table。这有效!

什么是回发,数组没有绑定到数组。

我做错了什么?

我有 2 个模型:

  public class testmodel
    {
     

        [Required]
        public DateTime StartDateTime { get; set; }

        [Required]
        public DateTime EndDateTime { get; set; }

        public int? NumberOfSlots { get; set; }
    }

  public class testMainModel
    {
        public List<testmodel> AllDates { get; set; }
    }

控制器:

 public async Task<ActionResult> TestShifts()
        {
            Models.testMainModel model = new Models.testMainModel();

            List<Models.testmodel> testDates = new List<Models.testmodel>();

            model.AllDates = testDates;

            return View(model) ;
        }

        [HttpPost]
        public async Task<ActionResult> TestShifts(Models.testMainModel model)
        {

            var x = model;

            var y = 1;

            return View(model);
        }

查看:

@model WCSOReserves.Models.testMainModel
@{
    ViewBag.Title = "TestShifts";
}

<h2>TestShifts</h2>

@using (Html.BeginForm("TestShifts", "Events", FormMethod.Post))
{
<div>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>Start Date/Time</th>
                <th>End Date/Time</th>
                <th></th>
            </tr>
        </thead>
        <tbody id="eventDateTimes" data-event-dates-start-count="@(Model.AllDates.Count - 1)">
            @for (int i = 0; i < Model.AllDates.Count; i++)
            {
                <tr data-id="@i">
                    <td>
                        <input asp-for="@Model.AllDates[i].StartDateTime" class="form-control" />
                    </td>
                    <td>
                        <input asp-for="@Model.AllDates[i].EndDateTime" class="form-control" />
                    </td>
                    <td>
                        <button type="button" class="btn btn-sm btn-danger">
                            <i class="align-middle me-2 fas fa-fw fa-trash-alt"></i>
                        </button>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <div>
        <button type="button" class="btn btn-secondary" id="addDateTime">Add Shift</button>
    </div>
    <div>
        <input type="submit" class="btn btn-primary" id="Submit" value="Submit" />
    </div>
</div>
}
@section Scripts{
<script>
    $(document).ready(function () {
   
   
    $('button#addDateTime').on('click', function() {
        var countVal = parseInt($('#eventDateTimes').attr('data-event-dates-start-count'));
       
        countVal += 1;

        var inputStartDate = $('<input />').attr('type', 'datetime-local').attr('data-val', 'true')
            .attr('data-val-required', 'The Start Date Field is required.')
            .attr('id', 'testMainModel_AllDates_' + countVal + '__StartDateTime')
            .attr('name', 'testMainModel.AllDates[' + countVal + '].StartDateTime').addClass('form-control');

        var inputEndDate = $('<input />').attr('type', 'datetime-local').attr('data-val', 'true')
            .attr('data-val-required', 'The End Date Field is required.')
            .attr('id', 'testMainModel_AllDates_' + countVal + '__EndDateTime')
            .attr('name', 'testMainModel.AllDates[' + countVal + '].EndDateTime').addClass('form-control');

        var button = $('<button />').attr('type', 'button').addClass('btn btn-sm btn-danger')
            .append($('<i />').addClass('align-middle me-2 fas fa-fw fa-trash-alt'));

        var row = $('<tr />')
            .attr('data-id', countVal)
            .append($('<td />').append(inputStartDate))
            .append($('<td />').append(inputEndDate))
            .append($('<td />').append(button));

        $('#eventDateTimes').append(row);
       
        $('#eventDateTimes').attr('data-event-dates-start-count', countVal);
    });
   
    $(document).on('click',
        '#eventDateTimes tr td button',
        function() {
            $('tr[data-id="' + $(this).parent().parent().attr('data-id') + '"]').remove();
        });

   
});



</script>

js 有效,我可以动态添加行。但是,在回发时,模型是空的。

这里data-event-dates-start-count应该和总数一样。

尝试

<tbody id="eventDateTimes" data-event-dates-start-count="@(Model.AllDates.Count)">

而不是

<tbody id="eventDateTimes" data-event-dates-start-count="@(Model.AllDates.Count - 1)">

js works, I can add rows dynamically. However, on postback, the model is empty.

不仅是你的 post 背部。您甚至无法在导致 post返回空模型的后端接收模型。

模型绑定系统通过名称属性绑定 属性。您的前端名称属性类似于 testMainModel.AllDates[index].PropertyName,与后端不匹配。

一个简单的方法是更改​​您的 post 操作参数名称,如下所示:

[HttpPost]
public async Task<ActionResult> TestShifts(Models.testMainModel testMainModel)
{

    var x = testMainModel;

    var y = 1;

    return View(testMainModel);
}

另一种方法是,您可以将 nametestMainModel.AllDates[index].PropertyName 更改为 AllDates[index].PropertyName。这样你就不需要改变动作参数了。

var inputStartDate = $('<input />').attr('type', 'datetime-local').attr('data-val', 'true')
    .attr('data-val-required', 'The Start Date Field is required.')
    .attr('id', 'testMainModel_AllDates_' + countVal + '__StartDateTime')
    .attr('name', 'AllDates[' + countVal + '].StartDateTime').addClass('form-control');

var inputEndDate = $('<input />').attr('type', 'datetime-local').attr('data-val', 'true')
    .attr('data-val-required', 'The End Date Field is required.')
    .attr('id', 'testMainModel_AllDates_' + countVal + '__EndDateTime')
    .attr('name', 'AllDates[' + countVal + '].EndDateTime').addClass('form-control');

另外,ASP.NET没有标签助手,它使用Html助手。 Tag Helper 存在于 ASP.NET Core 中。所以如果你使用 ASP.NET,你需要更改下面的 html 代码:

<td>
    @Html.EditorFor(model => Model.AllDates[i].StartDateTime, new { htmlAttributes = new { @class = "form-control",@type= "datetime-local" } })
</td>
<td>
    @Html.EditorFor(model => Model.AllDates[i].EndDateTime, new { htmlAttributes = new { @class = "form-control", @type = "datetime-local" } })

</td>