如何解决使用模型绑定和POST请求在每个表行上实现删除按钮
在我看来,我有一个表,该表具有要用于删除特定行的表单。我使用一个foreach循环来生成一个隐藏的输入字段,其中包含要传递给控制器的行值和用于模型出价的asp-for
标签,以及一个提交按钮。
传递给控制器的值始终是第一行。我倾向于认为此行为的原因是,生成的输入字段都具有相同的name属性,因为asp-for
表达式对于foreach循环的每次迭代都是不变的。
是否有使用表单和POST请求来实现此目的的简单方法,还是应该只使用带有路由值的锚点(即GET请求)?
这是我的ViewModel:
public class RolesViewModel
}
public IList<AppUser> UsersInRole {get; set;}
public string SelectedRole {get; set;}
public RemoveUserFromRole RemoveUser {get; set;}
public class RemoveUserFromRole
{
public string UserName {get; set;}
public string RoleName {get; set;}
}
}
我的视图
<form method="post" asp-action="RemoveUser" id="removeUserForm"></form>
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
@foreach (var user in Model.UsersInRole)
{
<tr>
<td>@user.UserName</td>
<td class="text-center">
<input form="removeUserForm" asp-for="RemoveUser.UserName" type="hidden" value="@user.UserName" />
<input form="removeUserForm" asp-for="RemoveUser.RoleName" type="hidden" value="@Model.SelectedRoleName" />
<button form="removeUserForm" type="submit" class="btn btn-sm btn-link text-danger py-0 my-0">
<i class="fas fa-times"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
还有我在控制器中的操作方法
[HttpPost]
public async Task<IActionResult> RemoveUser(RolesViewModel model)
{
//model.RemoveUser.UserName always have the value from the first row
var user = await _userManager.FindByNameAsync(model.RemoveUser.UserName);
if (user == null)
return RolesError(await GetModel());
var result = await _userManager.RemoveFromRoleAsync(user,model.RemoveUser.RoleName);
if (!result.Succeeded)
return RolesError(await GetModel());
return RedirectToAction("Roles",new { roleName = model.RemoveUser.RoleName });
}
提前感谢您的时间。
解决方法
根据您的代码,我发现您有多个包含user.UserName
的隐藏文件。
如果单击提交按钮,它将所有隐藏的字段值上传到代码隐藏区,并且仅绑定第一个值,这就是为什么模型始终是第一个值的原因。
您可以在F12开发工具的网络中找到表单数据。
要解决此问题,我们有一个简单但不好的解决方案。
我们可以在您的表中设置多个表单标签,以避免将所有隐藏的归档用户名值都发布到控制器:
像下面这样:
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
@foreach (var user in Model.UsersInRole)
{ int i = 0;
<tr>
<td>@user.UserName</td>
<td class="text-center">
<form method="post" asp-action="RemoveUser" id="@user.UserName">
<input form="@user.UserName" name="RemoveUser.UserName" type="hidden" value="@user.UserName" />
<input form="@user.UserName" name="RemoveUser.RoleName" type="hidden" value="@Model.SelectedRole" />
<button form="@user.UserName" type="submit" class="btn btn-sm btn-link text-danger py-0 my-0">
<i class="fas fa-times">iiiii</i>
</button>
</form>
</td>
</tr>
}
</tbody>
</table>
如果选择这种方式,则应重建视图的所有HTML组成。
此外,您可以尝试使用ajax来满足您的要求,该解决方案比以前的解决方案更好。您可以根据提交按钮的ID或位置使用jquery获取正确的表单数据,然后使用jquery ajax将表单数据发布到控制器中。然后,您可以返回重定向URL而不是RedirectToAction
方法。
有关如何使用ajax发送表单数据的更多详细信息,您可以参考以下代码:
@model MVCRelatedIssue.Models.RolesViewModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<form method="post" asp-action="RemoveUser" id="removeUserForm">
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
@foreach (var user in Model.UsersInRole)
{
<tr>
<td>@user.UserName</td>
<td class="text-center">
<input form="removeUserForm" name="RemoveUser.UserName" type="hidden" value="@user.UserName" />
<input form="removeUserForm" name="RemoveUser.RoleName" type="hidden" value="@Model.SelectedRole" />
<button form="removeUserForm" type="submit" id="submit" class="btn btn-sm btn-link text-danger py-0 my-0 subbtn">
<i class="fas fa-times">iiiii</i>
</button>
</td>
</tr>
}
</tbody>
</table>
</form>
@section Scripts{
<script>
$(document).ready(function () {
$(".subbtn").bind("click",function (e) {
e.preventDefault();
var formdata = new FormData();
var UserName = $(this).prev().prev().val();
formdata.append("RemoveUser.UserName",UserName);
console.log(UserName);
var roleName = $(this).prev().val();
formdata.append("RemoveUser.RoleName",roleName);
console.log(roleName);
$.ajax({
type: "POST",url: "/RemoveUser/RemoveUser",data: formdata,contentType: false,processData: false,success: function (data) {
alert("success");
window.location.href = data;
}
});
});
});
</script>
}
控制器:
[HttpPost]
public async Task<IActionResult> RemoveUser(RolesViewModel model)
{
//model.RemoveUser.UserName always have the value from the first row
//var user = await _userManager.FindByNameAsync(model.RemoveUser.UserName);
//if (user == null)
// return RolesError(await GetModel());
//var result = await _userManager.RemoveFromRoleAsync(user,model.RemoveUser.RoleName);
//if (!result.Succeeded)
// return RolesError(await GetModel());
string redirecturl = "/RemoveUser/Roles?roleName=" + model.RemoveUser.RoleName;
return Ok(redirecturl);
}
结果:
,您可以使用删除链接 在视图中
@foreach (var user in Model.UsersInRole)
{
<a href="@Url.Action("RemoveUser","YOUR_Controller",new {username = user.UserName})"
onclick="return confirm('Do You want to Delete');"
</a>
}
在控制器中
[HttpGet]
public async Task<IActionResult> RemoveUser(String username)
{
// Get the user Object the delete it
}
,
我能够以最少的代码占用空间解决此问题。
事实证明,<td>
标签可以具有形式,因此,知道这一点,就可以在每一行上具有不同的形式,如下所示:
查看:
//Remove inline table form
<table id="userTable" class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">User name</th>
<th scope="col" class="text-center">Delete</th>
</tr>
</thead>
<tbody>
@foreach (var user in Model.UsersInRole)
{
<tr>
<td>@user.UserName</td>
<td class="text-center">
//now each form will have the correct,row-wise formdata
<form method="post" asp-action="RemoveUser">
<input asp-for="RemoveUser.UserName" type="hidden" value="@user.UserName" />
<input asp-for="RemoveUser.RoleName" type="hidden" value="@Model.SelectedRoleName" />
<button type="submit" class="btn btn-sm btn-link text-danger py-0 my-0">
<i class="fas fa-times"></i>
</button>
</form>
</td>
</tr>
}
</tbody>
</table>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。