【问题标题】:Add Roles to User using checkboxes使用复选框向用户添加角色
【发布时间】:2021-03-25 01:44:00
【问题描述】:

我正在开发 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();
        }
    }

【问题讨论】:

  • 如果您从调试模式尝试,您会得到 selectedRoles.ToList().Count 什么?
  • @coder_b 它说 Count = 0
  • hmm.. 希望这有助于解决问题stackoverflow.com/questions/62783005/…
  • @coder_b 谢谢伙计,但这并没有真正的帮助。

标签: asp.net asp.net-core razor asp.net-identity asp.net-roles


【解决方案1】:

首先,您需要知道对于复杂类型的每个属性,模型绑定会在源中查找名称模式prefix.property_name。如果没有找到,它只查找不带前缀的property_name。你的后端想要接收一个列表模型,所以你传递的应该是[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>

结果:

【讨论】:

    【解决方案2】:

    @user:3843256 看看这个示例,它工作正常,唯一的区别是您使用的是每个,这意味着绑定不会发生,更改为基于计数器的索引绑定

    Checkbox list binding

    【讨论】:

    • 我刚刚运行了你的小提琴,RoleName 产生了一个空值
    • 那真的没关系,因为我绑定了它不发布的标签,我希望没有人会改变角色名称不是吗?您在选择字段后更新您的使用对象
    猜你喜欢
    • 1970-01-01
    • 2018-09-03
    • 2018-09-10
    • 1970-01-01
    • 2021-12-15
    • 2022-01-16
    • 2020-09-09
    • 2019-11-10
    • 1970-01-01
    相关资源
    最近更新 更多