首页 > 解决方案 > 如何以一种形式发布多个用户?

问题描述

我想注册未知数量的用户,并希望避免为每个用户单独提交表单。

我想我已经找到了可以添加和删除用户行的视图(感谢这篇文章)。

但我似乎无法让它绑定到控制器 POST 方法。Users正在返回null

更新

添加[Bind("Users")]到控制器方法解决了null问题!现在我正在为这些行的不雅而苦苦挣扎。

更新 2

解决了!添加<input type="hidden" name="Users.Index" value="{some unique value}" />解决了索引问题。我现在可以认为索引是非顺序的,不用担心维护顺序。我已经用lastIndex时间戳替换了下面答案中介绍的内容。它可以是任何随机数,只要它对表单中的每一行都是唯一的。

这就是我现在所拥有的:

楷模

public class ApplicationUserViewModel
{
    public string Email { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class BatchUserRegistrationViewModel
{
    public List<ApplicationUserViewModel> Users { get; set; }
}

创建视图

@model NameSpace.Models.BatchUserRegistrationViewModel

<form asp-action="RegisterManyUsers">
    @if (Model.Users != null)
    {
        // This part is for when the ModelState is not valid, and POST redirects back to the view.
        // I want the submitted form data to persist.
        for (int i = 0; i < Model.Users.Count; i++)
        {
            <div id="inputFormRow">
                <div class="input-group mb-3">
                    <input type="hidden" name="Users.Index" value="@i" />
                    <input type="text" name="users[@i].Email">
                    <input type="text" name="users[@i].FirstName>
                    <input type="text" name="users[@i].LastName">
                    <div class="input-group-append">
                        <button id="removeRow" type="button">
                            (-) Remove row
                        </button>
                    </div>
                </div>
            </div>
        }
    }
    else
    {
        // This part is for a new, blank form:
        <div id="inputFormRow">
            <div class="input-group mb-3">
                <input type="hidden" name="Users.Index" value="0" />
                <input type="text" name="users[0].Email">
                <input type="text" name="users[0].FirstName">
                <input type="text" name="users[0].LastName">
                <div class="input-group-append">
                    <button id="removeRow" type="button">
                        (-) Remove row
                    </button>
                </div>
            </div>
        </div>
    }
    <div id="newRow"></div>
    <p>
        <button id="addRow" type="button">
            (+) Add row
        </button>
    </p>
    <p>
        <button type="submit">(v) Register users</button>
    </p>
</form>

客户端脚本

<script>
    // add row
    $("#addRow").click(function () {
        let ts = $.now();
        var html = '';
        html += '<div id="inputFormRow">';
        html += '    <div class="input-group mb-3">';
        html += '        <input type="hidden" name="Users.Index" value="' + ts + '" />';
        html += '        <input type="text" name="users[' + ts + '].Email">';
        html += '        <input type="text" name="users[' + ts + '].FirstName">';
        html += '        <input type="text" name="users[' + ts + '].LastName">';
        html += '        <div class="input-group-append">';
        html += '            <button id="removeRow" type="button">';
        html += '                (-) Remove row';
        html += '            </button>';
        html += '        </div>';
        html += '    </div>';
        html += '</div>';
        $('#newRow').append(html);
    });

    // remove row
    $(document).on('click', '#removeRow', function () {
        $(this).closest('#inputFormRow').remove();
    });
</script>

控制器 POST 方法

public async Task<IActionResult> RegisterManyUsers([Bind("Users")] BatchUserRegistrationViewModel BatchReg)
{
    if (ModelState.IsValid)
    {
        if (BatchReg.Users != null)
        {
            List<ApplicationUser> dbUsers = new();
            foreach (ApplicationUserViewModel user in BatchReg.Users)
            {
                dbUsers.Add(new ApplicationUser {
                    Email = user.Email,
                    FirstName = user.FirstName,
                    LastName = user.LastName
                });
            }
            db.AddRange(dbUsers);
            await db.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
    }
    return View(BatchReg);
}

标签: c#asp.net-core-mvcmodel-binding

解决方案


尝试这个 :

<script>
let lastIndex= 0 ;
// add row
$("#addRow").click(function () {
    var html = '';
    html += '<div id="inputFormRow">';
    html += '    <div class="input-group mb-3">';
    html += '        <input type="text" name="users['+lastIndex+'].Email">';
    html += '        <input type="text" name="users['+lastIndex+'].FirstName">';
    html += '        <input type="text" name="users['+lastIndex+'].LastName">';
    html += '        <div class="input-group-append">';
    html += '            <button id="removeRow" type="button">';
    html += '                (-) Remove row';
    html += '            </button>';
    html += '        </div>';
    html += '    </div>';
    html += '</div>';
    lastIndex=lastIndex+1;
    $('#newRow').append(html);
});

// remove row
$(document).on('click', '#removeRow', function () {
    lastIndex=lastIndex-1;
    $(this).closest('#inputFormRow').remove();
});

推荐阅读