如何制作编辑用户页面以从同一视图编辑用户详细信息和角色?

How do you make an Edit User page to edit user details and roles from the same view?

我有一个可能很简单的问题,但我似乎无法找到答案并且一直走入死胡同。我只想创建一个视图,我可以在其中从一个视图编辑用户信息和用户角色。我被告知了很多事情,并指出创建一个视图模型,以及简单的无关信息。我看过很多关于如何仅编辑用户信息或仅编辑用户角色的指南,但这些指南出现在单独的视图中,我找不到任何指向在单个视图中完成此操作的内容。

到目前为止我有什么

我可以列出所有用户及其角色,只是在创建用户或编辑用户时看不到要列出的角色。每次我试着说

通过 ID 查找此用户 - 没问题 通过 id 查找此用户角色 - 没问题

但是系统中有多个角色,我似乎无法获得要填充的字符串和列表。它要么为控制器弹出我,要么为视图中的每个语句弹出我。

public async Task<IActionResult> EditUser(string id)
        {
            var user = await _userManager.FindByIdAsync(id);

            var viewModel = new ApplicationUser();
            {
                viewModel.FirstName = user.FirstName;
                viewModel.LastName = user.LastName;
                viewModel.UserName = user.UserName;
                
                
            }
            var model = new List<UserRoles>();
            foreach (var role in _roleManager.Roles)
            {
                var roleModel = new UserRoles
            {
                RoleId = role.Id,
                RoleName = role.Name
            };
            if (await _userManager.IsInRoleAsync(user, role.Name))
            {
                roleModel.Selected = true;
            }
            else
            {
                roleModel.Selected = false;
            }
            model.Add(roleModel);

                UserDetailsViewModel userDetailsViewModel = new UserDetailsViewModel()
                {
                    UserName = user.UserName,
                    FirstName = user.FirstName,
                    LastName = user.LastName,
                    RoleName = roleModel


                };
            return View(viewModel);

        }

@使用Rabbit.Application.ViewModels

@model UserDetailsViewModel

<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
  
<form asp-action="Update" method="post">
<div class="form-group">
        <label asp-for="@Model.UserName"></label>
        <input asp-for="@Model.UserName" class="form-control" />
    </div>
        <div class="form-group">
        <label asp-for="@Model.FirstName"></label>
        <input asp-for="@Model.FirstName" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="@Model.LastName"></label>
        <input asp-for="@Model.LastName" class="form-control" />
    </div>

  <div class="form-group">
        <label for="password">Password</label>
        <input name="password" class="form-control" />
<div class="card-body">
            @for (int i = 0; i < Model.Count; i++)
            {
                <div class="form-check m-1">
                    <input type="hidden" asp-for="@Model[i].RoleName" />
                    <input asp-for="@Model[i].Selected" class="form-check-input" />
                    <label class="form-check-label" asp-for="@Model[i].Selected">
                        @Model[i].RoleName
                    </label>
                </div>
            }
            <div asp-validation-summary="All" class="text-danger"></div>
        </div>

    <div asp-validation-summary="All" class="text-danger"></div>
    <button type="submit" class="btn btn-primary">Save</button>
 
</form>

我的demo如下实现你的效果:

HomeController.cs:

        public IActionResult Index( )
        {

            //    var role1 = new Role() { RoleId = "a1", Name = "a1" };

            //    var role2 = new Role() { RoleId = "a2", Name = "a2" };

            //   var A1User = new User()
            //{
            //    UserId = "A1",
            //    UserName = "A1",
            //    FirstName = "A1",
            //    LastName = "A1",
            //    Password = "A1"
            //};
            //var pslist = new List<UserRole>()
            //    {  new UserRole(){User=A1User, Role=role1},
            //       new UserRole(){User=A1User, Role=role2}
            //    };
            //    _context.UserRole.AddRange(pslist);
            //    _context.SaveChanges();
            var user = _context.User.Include(u => u.UserRole).ThenInclude(u => u.Role).FirstOrDefault();

            var userRoles = new HashSet<string>(user.UserRole.Select(c => c.RoleId));
            var allrole = _context.Role.Select(c => new RoleViewModel()
            {
                RoleId = c.RoleId,
                Name = c.Name,
                Selected = userRoles.Contains(c.RoleId)
            }).ToList();
            var userDetaulsViewModel = new UserDetaulsViewModel();
            userDetaulsViewModel.User = user;
            userDetaulsViewModel.RoleViewModel = allrole;
            PopulateAssignedRoleData(user);
            return View(userDetaulsViewModel);
        }


        private void PopulateAssignedRoleData(User user)

        {
            var allRoles = _context.Role;
            var userRoles = new HashSet<string>(user.UserRole.Select(c => c.RoleId));
            var roleViewModel = new List<RoleViewModel>();
            foreach (var role in allRoles)
            {
                roleViewModel.Add(new RoleViewModel
                {
                    RoleId = role.RoleId,
                    Name = role.Name,
                    Selected = userRoles.Contains(role.RoleId)
                });
            }
            ViewData["Roles"] = roleViewModel;

        }

        private void UpdateUserRole(string[] selectedRoles, User userToUpdate)
        {
            if (selectedRoles == null)
            {
                userToUpdate.UserRole = new List<UserRole>();
                return;
            }
            var selectedRolesHS = new HashSet<string>(selectedRoles);
            var userRoles = new HashSet<string>(userToUpdate.UserRole.Select(c => c.Role.RoleId));

            foreach (var role in _context.Role)
            {
                if (selectedRolesHS.Contains(role.RoleId))
                {
                    if (!userRoles.Contains(role.RoleId))
                    {
                        userToUpdate.UserRole.Add(new UserRole { UserId = userToUpdate.UserId, RoleId = role.RoleId });
                    }
                }
                else
                {

                    if (userRoles.Contains(role.RoleId))
                    {
                        UserRole roleToRemove = userToUpdate.UserRole.FirstOrDefault(i => i.RoleId == role.RoleId);
                        _context.Remove(roleToRemove);
                    }
                }
            }
        }


        [HttpPost]

        public async Task<IActionResult> Update( string[] selectedRoles)
        {   var userToUpdate = _context.User.Include(i=>i.UserRole).ThenInclude(i => i.Role).FirstOrDefault();
            UpdateUserRole(selectedRoles, userToUpdate);
            try
                {
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateException /* ex */)
                {
                    //Log the error (uncomment ex variable name and write a log.)
                    ModelState.AddModelError("", "Unable to save changes. " +
                        "Try again, and if the problem persists, " +
                        "see your system administrator.");
                }              
                PopulateAssignedRoleData(userToUpdate);
                return RedirectToAction(nameof(Index));
        }

Index.cshtml:

@model EditWithUser6.ViewModels.UserDetaulsViewModel


<h1 class="bg-info text-white">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
 
<form  asp-controller="home" asp-action="Update" method="post">
<div class="form-group">
        <label asp-for="User.UserName"></label>
        <input asp-for="User.UserName" class="form-control" />
    </div>
        <div class="form-group">
        <label asp-for="User.FirstName"></label>
        <input asp-for="User.FirstName" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="User.LastName"></label>
        <input asp-for="User.LastName" class="form-control" />
    </div>

 <div class="form-group">
        <label asp-for="User.Password"></label>
        <input asp-for="User.Password" class="form-control" />
    </div>

<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <table>
            <tr>
                @{
                    int cnt = 0;
                    List<EditWithUser6.ViewModels.RoleViewModel> roles = ViewBag.Roles;

                    foreach (var role in roles)
                    {
                        if (cnt++ % 3 == 0)
                        {
                            @:</tr><tr>
                        }
                        @:<td>
                            <input type="checkbox"
                                   name="selectedRoles"
                                   value="@role.RoleId"
                                   @(Html.Raw(role.Selected ? "checked=\"checked\"" : "")) />
                                   @role.RoleId /*@:  @role.Name*/ add id or name or both 
                            @:</td>
                    }
                    @:</tr>
                }
        </table>
    </div>
</div>

    <div asp-validation-summary="All" class="text-danger"></div>
    <button type="submit" class="btn btn-primary">Save</button>
 <input type="hidden" asp-for="User.UserId" />
</form>

Role.cs:

 public class Role

    {
        public string RoleId { get; set; }

        public string Name { get; set; }
     
        public virtual List<UserRole> UserRole { get; set; }
    }

User.cs:

public class User

    {
        public string UserId { get; set; }

        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Password { get; set; }
        public virtual List<UserRole> UserRole { get; set; }
    }

用户Role.cs:

 public class UserRole

    {
        [Key]
        public string UserId { get; set; }
        public User User { get; set; }
        [Key]
        public string RoleId { get; set; }
        public Role Role { get; set; }
    }

EditWithUser6Context.cs:

 public class EditWithUser6Context: DbContext

    {
        public EditWithUser6Context(DbContextOptions<EditWithUser6Context> options)
                   : base(options)
        {
        }

        public DbSet<User> User { get; set; }
        public DbSet<Role> Role { get; set; }

        public DbSet<UserRole> UserRole { get; set; }
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<UserRole>().HasKey(i => new { i.UserId, i.RoleId });
        }
    }

RoleViewModel.cs:

public class RoleViewModel

    {
        public string RoleId { get; set; }
        public bool Selected { get; set; }
        public string Name { get; set; }
    }

UserDetaulsViewModel.cs:

public class UserDetaulsViewModel

    {
        public User User { get; set; }
       
        public List<RoleViewModel> RoleViewModel { get; set; }
}

结果: