将 ViewModel 值传递给按钮或 ActionLink 单击上的 MVC 控制器操作方法
Passing ViewModel values to MVC Controller action method on button or ActionLink click
我有一个 asp.net/razor 页面,其中有几个下拉菜单,我尝试创建一个按钮或操作链接,在 "AccountController" class 并将下拉列表中选择的值传递给该方法。我一直在尝试各种方法,但 none 中的方法非常有效:
@model SpecSelRepos.Models.AccountViewModels.ManageRolesViewModel
<fieldset>
<label for="selectUserName">Users:</label>
<select asp-for="ManageRolesUser" asp-items="Model.Users"></select>
<label for="selectRoleName">Roles:</label>
<select asp-for="ManageRolesRole" asp-items="Model.Roles"></select>
@*button 1*@
@using (Html.BeginForm("AssignRole", "Account"))
{
<input type="submit" value="Add User to Role" name="buttonAddUserToRole">
}
@*button 2*@
<button class="btn btn-info" type="button" name="assignRole" onclick="location.href='@Url.Action("AssignRole", "Account", new { email = Model.ManageRolesUser, role = Model.ManageRolesRole })'"></button>
@*link 1*@
@Html.ActionLink("Assign Role", "AssignRole", "Account", new { email = Model.ManageRolesUser, role = Model.ManageRolesRole }, null)
@*link 2*@
@Html.ActionLink("Assign Role", "AssignRole", "Account", new { email = Model.ManageRolesUser, role = Model.ManageRolesRole })
</fieldset>
在 class AccountController 中,我有以下操作方法:
public async Task<IActionResult> AssignRole(string email, string role)
{
ApplicationUser user = GetUserByEmail(email);
if(null == user)
{
return Content("No user with given email:" + email);
}
// if the role exists, assign the role to the user
if (await _roleManager.RoleExistsAsync(role))
{
if(!await _userManager.IsInRoleAsync(user, role))
{
await _userManager.AddToRoleAsync(user, role);
return Content("Role assigned: " + GetUserRoles(user));
}
else
{
return Content ("User is in role: " + role + ": " + GetUserRoles(user));
}
}
else
{
return Content("Role: " + role + " does not exist");
}
}
点击按钮1无明显效果。按钮 2 和两个链接似乎都调用了 AssignRole 方法,但所有 3 个都抛出空值错误:
ArgumentNullException: Value cannot be null.
Parameter name: email
Microsoft.AspNetCore.Identity.UserManager.FindByEmailAsync(string email)
SpecSelRepos.Controllers.AccountController.GetUserByEmail(string email) in AccountController.cs
+ return _userManager.FindByEmailAsync(email).Result;
SpecSelRepos.Controllers.AccountController+<AssignRole>d__10.MoveNext() in AccountController.cs
+ ApplicationUser user = GetUserByEmail(email);
因此,该方法似乎已按需调用,但视图模型中的值作为空值传递,而不是在下拉框中选择的值。
这是视图模型class:
public class ManageRolesViewModel
{
private readonly UserManager<ApplicationUser> _userManager;
public ManageRolesViewModel(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
Users = new SelectList(userManager.Users.ToList());
Roles = new SelectList(roleManager.Roles.ToList());
}
public SelectList Users;
public SelectList Roles;
public string ManageRolesUser { get; set; }//contains the specific user the user selects
public string ManageRolesRole { get; set; }//contains the specific role the user selects
public List<ApplicationUser> GetUsersInRole(string role)
{
var users = _userManager.GetUsersInRoleAsync(role).Result.ToList();
return users;
}
}
一些帮助将不胜感激。
将您的视图更改为如下所示,我使用了带有表单方法和操作的表单,这将确保表单内的任何输入都序列化为与它们同名的参数
@model WebApplication3.Models.ManageRolesViewModel
<fieldset>
@using (Html.BeginForm("AssignRole", "Account", FormMethod.Get))
{
<span>
<label for="email">Users:</label>
@Html.DropDownList("email", @Model.Users)
</span>
<span>
<label for="role">Roles:</label>
@Html.DropDownList("role", @Model.Roles)
</span>
<input class="btn btn-info" type="submit" name="assignRole"/>
}
</fieldset>
由于 "email" 和 "role" 匹配控制器签名中的参数,因此将传递所选 ID(不是文本值)
当然,前提是您传递给视图的 selectList 已填充 "dataValueField" 和 "dataTextField"。
我还(不一定需要)将您的 AssignRoles 方法归因于:
[HttpGet]
但这只是为了冗长。我坚持一致性:)
我有一个 asp.net/razor 页面,其中有几个下拉菜单,我尝试创建一个按钮或操作链接,在 "AccountController" class 并将下拉列表中选择的值传递给该方法。我一直在尝试各种方法,但 none 中的方法非常有效:
@model SpecSelRepos.Models.AccountViewModels.ManageRolesViewModel
<fieldset>
<label for="selectUserName">Users:</label>
<select asp-for="ManageRolesUser" asp-items="Model.Users"></select>
<label for="selectRoleName">Roles:</label>
<select asp-for="ManageRolesRole" asp-items="Model.Roles"></select>
@*button 1*@
@using (Html.BeginForm("AssignRole", "Account"))
{
<input type="submit" value="Add User to Role" name="buttonAddUserToRole">
}
@*button 2*@
<button class="btn btn-info" type="button" name="assignRole" onclick="location.href='@Url.Action("AssignRole", "Account", new { email = Model.ManageRolesUser, role = Model.ManageRolesRole })'"></button>
@*link 1*@
@Html.ActionLink("Assign Role", "AssignRole", "Account", new { email = Model.ManageRolesUser, role = Model.ManageRolesRole }, null)
@*link 2*@
@Html.ActionLink("Assign Role", "AssignRole", "Account", new { email = Model.ManageRolesUser, role = Model.ManageRolesRole })
</fieldset>
在 class AccountController 中,我有以下操作方法:
public async Task<IActionResult> AssignRole(string email, string role)
{
ApplicationUser user = GetUserByEmail(email);
if(null == user)
{
return Content("No user with given email:" + email);
}
// if the role exists, assign the role to the user
if (await _roleManager.RoleExistsAsync(role))
{
if(!await _userManager.IsInRoleAsync(user, role))
{
await _userManager.AddToRoleAsync(user, role);
return Content("Role assigned: " + GetUserRoles(user));
}
else
{
return Content ("User is in role: " + role + ": " + GetUserRoles(user));
}
}
else
{
return Content("Role: " + role + " does not exist");
}
}
点击按钮1无明显效果。按钮 2 和两个链接似乎都调用了 AssignRole 方法,但所有 3 个都抛出空值错误:
ArgumentNullException: Value cannot be null.
Parameter name: email
Microsoft.AspNetCore.Identity.UserManager.FindByEmailAsync(string email)
SpecSelRepos.Controllers.AccountController.GetUserByEmail(string email) in AccountController.cs
+ return _userManager.FindByEmailAsync(email).Result;
SpecSelRepos.Controllers.AccountController+<AssignRole>d__10.MoveNext() in AccountController.cs
+ ApplicationUser user = GetUserByEmail(email);
因此,该方法似乎已按需调用,但视图模型中的值作为空值传递,而不是在下拉框中选择的值。
这是视图模型class:
public class ManageRolesViewModel
{
private readonly UserManager<ApplicationUser> _userManager;
public ManageRolesViewModel(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
Users = new SelectList(userManager.Users.ToList());
Roles = new SelectList(roleManager.Roles.ToList());
}
public SelectList Users;
public SelectList Roles;
public string ManageRolesUser { get; set; }//contains the specific user the user selects
public string ManageRolesRole { get; set; }//contains the specific role the user selects
public List<ApplicationUser> GetUsersInRole(string role)
{
var users = _userManager.GetUsersInRoleAsync(role).Result.ToList();
return users;
}
}
一些帮助将不胜感激。
将您的视图更改为如下所示,我使用了带有表单方法和操作的表单,这将确保表单内的任何输入都序列化为与它们同名的参数
@model WebApplication3.Models.ManageRolesViewModel
<fieldset>
@using (Html.BeginForm("AssignRole", "Account", FormMethod.Get))
{
<span>
<label for="email">Users:</label>
@Html.DropDownList("email", @Model.Users)
</span>
<span>
<label for="role">Roles:</label>
@Html.DropDownList("role", @Model.Roles)
</span>
<input class="btn btn-info" type="submit" name="assignRole"/>
}
</fieldset>
由于 "email" 和 "role" 匹配控制器签名中的参数,因此将传递所选 ID(不是文本值)
当然,前提是您传递给视图的 selectList 已填充 "dataValueField" 和 "dataTextField"。
我还(不一定需要)将您的 AssignRoles 方法归因于: [HttpGet]
但这只是为了冗长。我坚持一致性:)