【发布时间】:2021-12-07 00:49:14
【问题描述】:
我想注册未知数量的用户,并希望避免为每个用户单独提交表单。
我想我已经找到了可以添加和删除用户行的视图(感谢this 文章)。
但我似乎无法让它绑定到控制器的 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);
}
【问题讨论】:
-
你添加的行名不正确,应该是users[0].Email
-
可以通过在脚本中定义一个全局变量来实现
标签: c# asp.net-core-mvc model-binding