提交按钮发送空白(无数据)数据 MVC ASP.Net
Submit button sending blank(No data) Data MVC ASP.Net
在Core MVC的项目中,ASP.Net 5,我有一个简单的任务,允许超级管理员更新用户角色。但到目前为止我唯一能做到的就是让提交按钮到达控制器。
但是呈现的数据是空白的。我正在尝试将用户 ID 发送回控制器以更新记录,然后 return 更新的用户列表作为视图。
我在 table 中显示用户,每一行都有角色更新选项。
我的代码片段来自视图:
@using (Html.BeginForm("SuperAdminEdit", "Referral", FormMethod.Post))
{
<table class="table">
<thead>
<tr>
<th>
Email
</th>
<th>
Role
</th>
</tr>
</thead>
<tbody>
@if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>
@item.Key
</td>
<td>
<input asp-for="@item.Key" type="text" id="chosen+@item.Key" value="" style="display: none;" />
<select id="@item.Key" class="form-control">
@{
string[] roles = { "User", "Admin", "Super Admin" };
foreach (var role in roles)
{
if (role.Equals(item.Value))
{
<option selected> @role </option>
}
else
{
<option> @role </option>
}
}
}
</select>
<script type="text/javascript">
document.getElementById('@item.Key').addEventListener('change', function () {
document.getElementById('chosen+@item.Key').value = document.getElementById('@item.Key').selectedOptions[0].value;
console.log(document.getElementById('chosen+@item.Key').value);
});
</script>
</td>
<td>
<input id="submit+@item.Key" type="submit" value="Update" class="btn btn-primary" />
</td>
</tr>
}
}
</tbody>
</table>
}
处理编辑的控制器:
[HttpPost]
public ActionResult SuperAdminEdit(string data)
{
Console.WriteLine("New role is "+data);
SqlConnection conn = new SqlConnection...............................
conn.Open();
//Rest of the Code
}
当我从控制器方法打印消息时,它正在打印但值是空白。
请帮助理解问题。
表单提交旨在提交模型,在您的情况下,它看起来是一组用户。然后,您正在创建一个旨在接受新角色的操作,但是新角色是什么项目?就该方法而言,您已经告诉它期待一个角色,但除此之外它什么都不知道。表单通常用于以下情况:您有一个用户列表,但访问了一个包含单个用户表单的页面,该表单将被更新和提交,而不是一个页面列出许多可以单独更新的行。
如果您正在呈现用户列表并希望能够更改他们的每个角色并在每行的基础上提交更新,您不需要类型的“提交”按钮,而是输入“button”按钮,这将使 Ajax 回调到控制器上的 POST 操作,提供 ID(好吧,在你的情况下,看起来你只是传递用户名 [Key] ) 和更新后的角色。这样控制器就可以按名称加载适用的用户,并在保留更改之前更新该用户的角色。
通常作为起点,我建议加载一个包含视图所需的所有数据的视图模型。在你的情况下是这样的:
[Serializable]
public class UserEditViewModel
{
public ICollection<UserViewModel> Users { get; set; } = new List<UserViewModel>();
public ICollection<RoleViewModel> Roles { get; set; } = new List<RoleViewModel>();
}
[Serializable]
public class UserViewModel
{
public int UserId { get; set; }
public string Name { get; set; }
public int? RoleId { get; set; }
}
[Serializable]
public class RoleViewModel
{
public int RoleId { get; set; }
public string Name { get; set; }
}
然后,当您加载数据时,使用 Select
或 Automapper 的 ProjectTo
来构建您的用户集合和角色查找列表,并填充一个 UserEditViewModel 作为您页面的模型。从那里,您可以从模型的“角色”集合(而不是角色名称的硬编码列表)构建 <select>
列表,并 select 每个用户行的适当列表。
动态更新行 table 可能有点令人生畏,但有一些事情可以帮助您,例如为控件生成唯一 ID(您正在做的)和利用 data-
属性。给猫剥皮的方法有很多,还有很多示例可供考虑,还有最佳实践,例如在何处放置脚本块。 (绝对不在 table 行内!)
作为选项的简单演示:
foreach (var user in Model.Users)
{
<tr>
<td>
@user.Name
</td>
<td>
<select id="role-@user.UserId" class="form-control">
foreach (var role in Model.Roles)
{
if (role.RoleId == user.RoleId)
{
<option selected data-role-id=@role.RoleId> @role.Name </option>
}
else
{
<option data-role-id=@role.RoleId> @role.Name </option>
}
}
</select>
</td>
<td>
<input id="update+@user.UserId" type="button" value="Update" class="btn btn-primary update-button" data-user-id=@user.UserId />
</td>
</tr>
}
这里的主要区别在于页面的模型现在将成为我们的 UserEditViewModel,因此我们可以访问行源的用户集合和查找的角色集合。更新按钮现在不是提交类型按钮,我们给它一个 class 的“update-button”作为 jQuery 的标记,并为它关联的 UserId 设置一个 data-user-id 属性到.
在指定的脚本块中,您可以使用
$(document).ready(function() {
$('.update-button').on('click', function(e) {
var userId = $(this).data("user-id");
var newRoleId = $('#role-' + userId).find(':selected').data('role-id`);
updateUserRole(userId, newRoleId);
});
};
function updateUserRole(userId, newRoleId) {
$.ajax({
url: "@Url.Action("UpdateUserRole", "User")",
type: "POST",
dataType: "json",
data: { userId: userId, newRoleId: newRoleId },
success: function (result) {
// TODO: Handle result.
},
error: function (xhr, status, error) {
// TODO: Handle error.
}
});
}
这里的“data-”属性对于将模型中的有用细节传递到控件中很有用,例如每个按钮应该应用的 UserId,然后使用它来找到角色的适当 select 列表,然后从 selected 选项中获取角色 ID。这确实需要一些错误处理并检查一个角色是否确实 selected。
然后在你的控制器中:
[HttpPost]
public JsonResult UpdateUserRole(int userId, int newRoleId)
{
try
{
// TODO, logic to load the user, update it's role and save changes.
using(var context = new AppDbContext())
{
var user = context.Users.Include(x => x.Role)
.Single(x => x.UserId == userId);
var newRole = context.Roles.Single(x => x.RoleId == newRoleId);
user.Role = newRole;
context.SaveChanges();
}
return Json(new { success = true });
}
catch(Exception ex)
{
return Json(new { success = false, message = "An unexpected error occurred." });
}
}
如果您使用的是 EF,则不会打开 SQL 连接,而是实例化应用程序 DbContext 实例、获取用户、更新其属性并调用 SaveChanges()
.
这个例子不是完整的代码,是凭记忆写的。它应该为您提供一个考虑的起点,并且肯定会有大量示例以及有关使用 Ajax、表单等的最佳实践的建议
在Core MVC的项目中,ASP.Net 5,我有一个简单的任务,允许超级管理员更新用户角色。但到目前为止我唯一能做到的就是让提交按钮到达控制器。
但是呈现的数据是空白的。我正在尝试将用户 ID 发送回控制器以更新记录,然后 return 更新的用户列表作为视图。
我在 table 中显示用户,每一行都有角色更新选项。
我的代码片段来自视图:
@using (Html.BeginForm("SuperAdminEdit", "Referral", FormMethod.Post))
{
<table class="table">
<thead>
<tr>
<th>
Email
</th>
<th>
Role
</th>
</tr>
</thead>
<tbody>
@if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>
@item.Key
</td>
<td>
<input asp-for="@item.Key" type="text" id="chosen+@item.Key" value="" style="display: none;" />
<select id="@item.Key" class="form-control">
@{
string[] roles = { "User", "Admin", "Super Admin" };
foreach (var role in roles)
{
if (role.Equals(item.Value))
{
<option selected> @role </option>
}
else
{
<option> @role </option>
}
}
}
</select>
<script type="text/javascript">
document.getElementById('@item.Key').addEventListener('change', function () {
document.getElementById('chosen+@item.Key').value = document.getElementById('@item.Key').selectedOptions[0].value;
console.log(document.getElementById('chosen+@item.Key').value);
});
</script>
</td>
<td>
<input id="submit+@item.Key" type="submit" value="Update" class="btn btn-primary" />
</td>
</tr>
}
}
</tbody>
</table>
}
处理编辑的控制器:
[HttpPost]
public ActionResult SuperAdminEdit(string data)
{
Console.WriteLine("New role is "+data);
SqlConnection conn = new SqlConnection...............................
conn.Open();
//Rest of the Code
}
当我从控制器方法打印消息时,它正在打印但值是空白。
请帮助理解问题。
表单提交旨在提交模型,在您的情况下,它看起来是一组用户。然后,您正在创建一个旨在接受新角色的操作,但是新角色是什么项目?就该方法而言,您已经告诉它期待一个角色,但除此之外它什么都不知道。表单通常用于以下情况:您有一个用户列表,但访问了一个包含单个用户表单的页面,该表单将被更新和提交,而不是一个页面列出许多可以单独更新的行。
如果您正在呈现用户列表并希望能够更改他们的每个角色并在每行的基础上提交更新,您不需要类型的“提交”按钮,而是输入“button”按钮,这将使 Ajax 回调到控制器上的 POST 操作,提供 ID(好吧,在你的情况下,看起来你只是传递用户名 [Key] ) 和更新后的角色。这样控制器就可以按名称加载适用的用户,并在保留更改之前更新该用户的角色。
通常作为起点,我建议加载一个包含视图所需的所有数据的视图模型。在你的情况下是这样的:
[Serializable]
public class UserEditViewModel
{
public ICollection<UserViewModel> Users { get; set; } = new List<UserViewModel>();
public ICollection<RoleViewModel> Roles { get; set; } = new List<RoleViewModel>();
}
[Serializable]
public class UserViewModel
{
public int UserId { get; set; }
public string Name { get; set; }
public int? RoleId { get; set; }
}
[Serializable]
public class RoleViewModel
{
public int RoleId { get; set; }
public string Name { get; set; }
}
然后,当您加载数据时,使用 Select
或 Automapper 的 ProjectTo
来构建您的用户集合和角色查找列表,并填充一个 UserEditViewModel 作为您页面的模型。从那里,您可以从模型的“角色”集合(而不是角色名称的硬编码列表)构建 <select>
列表,并 select 每个用户行的适当列表。
动态更新行 table 可能有点令人生畏,但有一些事情可以帮助您,例如为控件生成唯一 ID(您正在做的)和利用 data-
属性。给猫剥皮的方法有很多,还有很多示例可供考虑,还有最佳实践,例如在何处放置脚本块。 (绝对不在 table 行内!)
作为选项的简单演示:
foreach (var user in Model.Users)
{
<tr>
<td>
@user.Name
</td>
<td>
<select id="role-@user.UserId" class="form-control">
foreach (var role in Model.Roles)
{
if (role.RoleId == user.RoleId)
{
<option selected data-role-id=@role.RoleId> @role.Name </option>
}
else
{
<option data-role-id=@role.RoleId> @role.Name </option>
}
}
</select>
</td>
<td>
<input id="update+@user.UserId" type="button" value="Update" class="btn btn-primary update-button" data-user-id=@user.UserId />
</td>
</tr>
}
这里的主要区别在于页面的模型现在将成为我们的 UserEditViewModel,因此我们可以访问行源的用户集合和查找的角色集合。更新按钮现在不是提交类型按钮,我们给它一个 class 的“update-button”作为 jQuery 的标记,并为它关联的 UserId 设置一个 data-user-id 属性到.
在指定的脚本块中,您可以使用
$(document).ready(function() {
$('.update-button').on('click', function(e) {
var userId = $(this).data("user-id");
var newRoleId = $('#role-' + userId).find(':selected').data('role-id`);
updateUserRole(userId, newRoleId);
});
};
function updateUserRole(userId, newRoleId) {
$.ajax({
url: "@Url.Action("UpdateUserRole", "User")",
type: "POST",
dataType: "json",
data: { userId: userId, newRoleId: newRoleId },
success: function (result) {
// TODO: Handle result.
},
error: function (xhr, status, error) {
// TODO: Handle error.
}
});
}
这里的“data-”属性对于将模型中的有用细节传递到控件中很有用,例如每个按钮应该应用的 UserId,然后使用它来找到角色的适当 select 列表,然后从 selected 选项中获取角色 ID。这确实需要一些错误处理并检查一个角色是否确实 selected。
然后在你的控制器中:
[HttpPost]
public JsonResult UpdateUserRole(int userId, int newRoleId)
{
try
{
// TODO, logic to load the user, update it's role and save changes.
using(var context = new AppDbContext())
{
var user = context.Users.Include(x => x.Role)
.Single(x => x.UserId == userId);
var newRole = context.Roles.Single(x => x.RoleId == newRoleId);
user.Role = newRole;
context.SaveChanges();
}
return Json(new { success = true });
}
catch(Exception ex)
{
return Json(new { success = false, message = "An unexpected error occurred." });
}
}
如果您使用的是 EF,则不会打开 SQL 连接,而是实例化应用程序 DbContext 实例、获取用户、更新其属性并调用 SaveChanges()
.
这个例子不是完整的代码,是凭记忆写的。它应该为您提供一个考虑的起点,并且肯定会有大量示例以及有关使用 Ajax、表单等的最佳实践的建议