使用复选框为用户添加角色
Add Roles to User using checkboxes
我正在开发 Razor 应用程序,我需要管理员分配或更新用户的角色。我正在使用复选框来执行此操作。到目前为止,我已经能够填充视图以显示用户及其在复选框中勾选的各自角色,但我无法更新他们的角色,因为任何时候勾选复选框以添加角色时,它都不会t 将角色添加到用户。我认为这一行是罪魁祸首:var selectedRoles = model.Where(x => x.Selected).Select(y => y.RoleName);
.
这是模特:
public class ManageUserRolesViewModel
{
public string RoleId { get; set; }
public string RoleName { get; set; }
public bool Selected { get; set; }
}
这是页面:
<form method="post">
<div class="card">
<div class="card-header">
<h2>Manage User Roles</h2>
Add / Remove Roles for @Model.UserID
</div>
<div class="card-body">
@foreach (var x in Model.UserRoles)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@x.RoleId" />
<input type="hidden" asp-for="@x.RoleName" />
<input asp-for="@x.Selected" class="form-check-input" />
<label class="form-check-label" asp-for="@x.Selected">
@x.RoleName
</label>
</div>
}
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div class="card-footer">
<input type="submit" value="Update" class="btn btn-primary" style="width:auto" />
<a asp-page="/Account/UserManagement/UserList" class="btn btn-primary" style="width:auto">Cancel</a>
</div>
</div>
</form>
这是页面模型:
public class ManageModel : PageModel
{
private readonly RoleManager<IdentityRole> _roleManager;
private readonly BankAssesmentApplicationIdentityDbContext _db;
private readonly UserManager<IdentityUser> _userManager;
public ManageModel(
RoleManager<IdentityRole> roleManager,
UserManager<IdentityUser> userManager,
BankAssesmentApplicationIdentityDbContext db)
{
_db = db;
_userManager = userManager;
_roleManager = roleManager;
}
public IList<ManageUserRolesViewModel> UserRoles = new List<ManageUserRolesViewModel>();
public string UserID { get; set; }
public async Task<IActionResult> OnPostAsync(List<ManageUserRolesViewModel> model, string userId)
{
UserID = userId;
if (ModelState.IsValid)
{
IdentityUser user = await _userManager.FindByNameAsync(userId);
if (user == null)
{
return Page();
}
var roles = await _userManager.GetRolesAsync(user);
var result = await _userManager.RemoveFromRolesAsync(user, roles);
if (!result.Succeeded)
{
ModelState.AddModelError("", "Cannot remove user existing roles");
return Page();
}
var selectedRoles = model.Where(x => x.Selected).Select(y => y.RoleName);
await _userManager.AddToRolesAsync(user, selectedRoles);
if (!result.Succeeded)
{
ModelState.AddModelError("", "Cannot add selected roles to user");
return Page();
}
return RedirectToPage("/Account/UserManagement/UserList");
}
return Page();
}
public async Task<IActionResult> OnGetAsync(string userId)
{
UserID = userId;
var user = await _userManager.FindByEmailAsync(userId);
if (user == null)
{
return Page();
}
var model = new List<ManageUserRolesViewModel>();
foreach (var role in _roleManager.Roles.ToList())
{
ManageUserRolesViewModel roles = new ManageUserRolesViewModel
{
RoleId = role.Id,
RoleName = role.Name,
};
UserRoles.Add(roles);
if (await _userManager.IsInRoleAsync(user, role.Name))
{
roles.Selected = true;
}
else
{
roles.Selected = false;
}
model.Add(roles);
}
return Page();
}
}
@user:3843256 看看这个示例,它工作正常,唯一的区别是你正在为每个使用,这意味着绑定不会发生,更改为基于计数器的索引绑定
首先,您需要知道对于复杂类型的每个 属性,模型绑定会在源中查找名称模式 prefix.property_name
。如果没有找到,它只查找 property_name
而没有 prefix.Your 后端想要接收列表模型,所以你传递的应该是 [index].PropertyName
。但你所做的将导致服务器输入具有相同的名称,模型绑定系统无法匹配列表的值。
那么你需要知道asp-for="@x.Selected"
会为checkbox生成值,但是当你改变checkbox状态时它不会改变值,你需要创建一个点击事件来改变值:
<input asp-for="@x.Selected" onclick="$(this).val(this.checked ? true : false)"/>
您需要更改如下:
<form method="post">
<div class="card">
<div class="card-header">
<h2>Manage User Roles</h2>
Add / Remove Roles for @Model.UserID
</div>
<div class="card-body">
@*Begin change*@
@{ int i = 0;}
@foreach (var x in Model.UserRoles)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@x.RoleId" name="[@i].RoleId"/>
<input type="hidden" asp-for="@x.RoleName" name="[@i].RoleName"/>
<input asp-for="@x.Selected" name="[@i].Selected" class="form-check-input" onclick="$(this).val(this.checked ? true : false)"/>
<label class="form-check-label" asp-for="@x.Selected">
@x.RoleName
</label>
</div>
i++;
}
@*End change*@
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div class="card-footer">
<input type="submit" value="Update" class="btn btn-primary" style="width:auto" />
<a asp-page="/Account/UserManagement/UserList" class="btn btn-primary" style="width:auto">Cancel</a>
</div>
</div>
</form>
结果:
我正在开发 Razor 应用程序,我需要管理员分配或更新用户的角色。我正在使用复选框来执行此操作。到目前为止,我已经能够填充视图以显示用户及其在复选框中勾选的各自角色,但我无法更新他们的角色,因为任何时候勾选复选框以添加角色时,它都不会t 将角色添加到用户。我认为这一行是罪魁祸首:var selectedRoles = model.Where(x => x.Selected).Select(y => y.RoleName);
.
这是模特:
public class ManageUserRolesViewModel
{
public string RoleId { get; set; }
public string RoleName { get; set; }
public bool Selected { get; set; }
}
这是页面:
<form method="post">
<div class="card">
<div class="card-header">
<h2>Manage User Roles</h2>
Add / Remove Roles for @Model.UserID
</div>
<div class="card-body">
@foreach (var x in Model.UserRoles)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@x.RoleId" />
<input type="hidden" asp-for="@x.RoleName" />
<input asp-for="@x.Selected" class="form-check-input" />
<label class="form-check-label" asp-for="@x.Selected">
@x.RoleName
</label>
</div>
}
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div class="card-footer">
<input type="submit" value="Update" class="btn btn-primary" style="width:auto" />
<a asp-page="/Account/UserManagement/UserList" class="btn btn-primary" style="width:auto">Cancel</a>
</div>
</div>
</form>
这是页面模型:
public class ManageModel : PageModel
{
private readonly RoleManager<IdentityRole> _roleManager;
private readonly BankAssesmentApplicationIdentityDbContext _db;
private readonly UserManager<IdentityUser> _userManager;
public ManageModel(
RoleManager<IdentityRole> roleManager,
UserManager<IdentityUser> userManager,
BankAssesmentApplicationIdentityDbContext db)
{
_db = db;
_userManager = userManager;
_roleManager = roleManager;
}
public IList<ManageUserRolesViewModel> UserRoles = new List<ManageUserRolesViewModel>();
public string UserID { get; set; }
public async Task<IActionResult> OnPostAsync(List<ManageUserRolesViewModel> model, string userId)
{
UserID = userId;
if (ModelState.IsValid)
{
IdentityUser user = await _userManager.FindByNameAsync(userId);
if (user == null)
{
return Page();
}
var roles = await _userManager.GetRolesAsync(user);
var result = await _userManager.RemoveFromRolesAsync(user, roles);
if (!result.Succeeded)
{
ModelState.AddModelError("", "Cannot remove user existing roles");
return Page();
}
var selectedRoles = model.Where(x => x.Selected).Select(y => y.RoleName);
await _userManager.AddToRolesAsync(user, selectedRoles);
if (!result.Succeeded)
{
ModelState.AddModelError("", "Cannot add selected roles to user");
return Page();
}
return RedirectToPage("/Account/UserManagement/UserList");
}
return Page();
}
public async Task<IActionResult> OnGetAsync(string userId)
{
UserID = userId;
var user = await _userManager.FindByEmailAsync(userId);
if (user == null)
{
return Page();
}
var model = new List<ManageUserRolesViewModel>();
foreach (var role in _roleManager.Roles.ToList())
{
ManageUserRolesViewModel roles = new ManageUserRolesViewModel
{
RoleId = role.Id,
RoleName = role.Name,
};
UserRoles.Add(roles);
if (await _userManager.IsInRoleAsync(user, role.Name))
{
roles.Selected = true;
}
else
{
roles.Selected = false;
}
model.Add(roles);
}
return Page();
}
}
@user:3843256 看看这个示例,它工作正常,唯一的区别是你正在为每个使用,这意味着绑定不会发生,更改为基于计数器的索引绑定
首先,您需要知道对于复杂类型的每个 属性,模型绑定会在源中查找名称模式 prefix.property_name
。如果没有找到,它只查找 property_name
而没有 prefix.Your 后端想要接收列表模型,所以你传递的应该是 [index].PropertyName
。但你所做的将导致服务器输入具有相同的名称,模型绑定系统无法匹配列表的值。
那么你需要知道asp-for="@x.Selected"
会为checkbox生成值,但是当你改变checkbox状态时它不会改变值,你需要创建一个点击事件来改变值:
<input asp-for="@x.Selected" onclick="$(this).val(this.checked ? true : false)"/>
您需要更改如下:
<form method="post">
<div class="card">
<div class="card-header">
<h2>Manage User Roles</h2>
Add / Remove Roles for @Model.UserID
</div>
<div class="card-body">
@*Begin change*@
@{ int i = 0;}
@foreach (var x in Model.UserRoles)
{
<div class="form-check m-1">
<input type="hidden" asp-for="@x.RoleId" name="[@i].RoleId"/>
<input type="hidden" asp-for="@x.RoleName" name="[@i].RoleName"/>
<input asp-for="@x.Selected" name="[@i].Selected" class="form-check-input" onclick="$(this).val(this.checked ? true : false)"/>
<label class="form-check-label" asp-for="@x.Selected">
@x.RoleName
</label>
</div>
i++;
}
@*End change*@
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div class="card-footer">
<input type="submit" value="Update" class="btn btn-primary" style="width:auto" />
<a asp-page="/Account/UserManagement/UserList" class="btn btn-primary" style="width:auto">Cancel</a>
</div>
</div>
</form>
结果: