如何在ASP.NET MVC 5和身份(实体框架优先)中将用户链接到另一个用户

时间:2018-12-23 23:45:38

标签: c# asp.net-mvc-5 asp.net-identity

我需要使用实体框架代码优先方法将用户链接到ASP.NET MVC 5和ASP.NET身份的帮助。

这里的用例是,当我创建一个用户时,我需要在ReportsTo下拉列表中选择一个用户,该列表显示该用户的名字和姓氏,并将所选用户的ID保存在Identity User表的ReportsTo列中。该用户列表必须是数据库中现有Identity用户的列表。

我实现了各种主题,并设法获得了一个下拉列表,以与Identity用户一起在我的用户创建和编辑视图中显示。它将ID保存在数据库的ReportsTo列中,但是当我编辑用户时,ReportsTo字段不会将ID保存在数据库中,除非我再次在下拉列表中进行相同的选择(它将用如果我不再进行选择(因为它不会在编辑视图中加载以前保存的值),则显示为空白),然后在详细信息页面和用户列表中,将ReportsTo保存的用户显示为GUID。

在我的用户控制器中:

public UserController()
        {
            using (var userList = new ApplicationDbContext())
            {
                ViewBag.ReportsTo = userList.Users.Select(user => new SelectListItem { Text = user.FirstName + " " + user.LastName, Value = user.Id }).ToList();
            }
        } 

public ActionResult Create()
        {
            // Show a list of available groups:
            ViewBag.GroupsList =
                new SelectList(this.GroupManager.Groups, "Id", "Name");
            return View();
        } 

[HttpPost]
        public async Task<ActionResult> Create(RegisterViewModel userViewModel, params string[] selectedGroups)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser
                {
                    UserName = userViewModel.Email,
                    FirstName = userViewModel.FirstName,
                    LastName = userViewModel.LastName,
                    ReportsTo = userViewModel.ReportsTo,
                    OfficeNumber = userViewModel.OfficeNumber,
                    CellNumber = userViewModel.CellNumber,
                    Email = userViewModel.Email
                };
                var adminresult = await UserManager
                    .CreateAsync(user, userViewModel.Password);

                //Add User to the selected Groups 
                if (adminresult.Succeeded)
                {
                    if (selectedGroups != null)
                    {
                        selectedGroups = selectedGroups ?? new string[] { };
                        await this.GroupManager
                            .SetUserGroupsAsync(user.Id, selectedGroups);
                    }
                    return RedirectToAction("Users");
                }
            }
            ViewBag.Groups = new SelectList(
                await RoleManager.Roles.ToListAsync(), "Id", "Name");
            return View();
        } 

public async Task<ActionResult> Edit(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var user = await UserManager.FindByIdAsync(id);
            if (user == null)
            {
                return HttpNotFound();
            }

            // Display a list of available Groups:
            var allGroups = this.GroupManager.Groups;
            var userGroups = await this.GroupManager.GetUserGroupsAsync(id);

            var model = new EditUserViewModel()
            {
                Id = user.Id,
                Email = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName,
                ReportsTo = user.ReportsTo,
                OfficeNumber = user.OfficeNumber,
                CellNumber = user.CellNumber
            };

            foreach (var group in allGroups)
            {
                var listItem = new SelectListItem()
                {
                    Text = group.Name,
                    Value = group.Id,
                    Selected = userGroups.Any(g => g.Id == group.Id)
                };
                model.GroupsList.Add(listItem);
            }
            return View(model);
        } 

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit(
            [Bind(Include = "Email,Id,FirstName,LastName,ReportsTo,OfficeNumber,CellNumber")] EditUserViewModel editUser,
            params string[] selectedGroups)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindByIdAsync(editUser.Id);
                if (user == null)
                {
                    return HttpNotFound();
                }

                // Update the User:
                user.UserName = editUser.Email;
                user.Email = editUser.Email;
                user.FirstName = editUser.FirstName;
                user.LastName = editUser.LastName;
                user.ReportsTo = editUser.ReportsTo;
                user.OfficeNumber = editUser.OfficeNumber;
                user.CellNumber = editUser.CellNumber;
                await this.UserManager.UpdateAsync(user);

                // Update the Groups:
                selectedGroups = selectedGroups ?? new string[] { };
                await this.GroupManager.SetUserGroupsAsync(user.Id, selectedGroups);
                return RedirectToAction("Users");
            }
            ModelState.AddModelError("", "Something failed.");
            return View();
        } 

我的EditUserViewModel:

public class EditUserViewModel
    {
        public EditUserViewModel()
        {
            this.RolesList = new List<SelectListItem>();
            this.GroupsList = new List<SelectListItem>();
        }
        public string Id { get; set; }

        [Required(AllowEmptyStrings = false)]
        [Display(Name = "Email")]
        [EmailAddress]
        public string Email { get; set; }
        public string FirstName { get; set; }

        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Display(Name = "Reports To")]
        public string ReportsTo { get; set; }

        [Display(Name = "Office Number")]
        public string OfficeNumber { get; set; }

        [Display(Name = "Cell Number")]
        public string CellNumber { get; set; }

        [Display(Name = "ProfilePicture")]
        public byte[] ProfilePicture { get; set; }

        public ICollection<SelectListItem> RolesList { get; set; }

        public ICollection<SelectListItem> GroupsList { get; set; }
    } 

我的创建和编辑视图中的下拉列表

@Html.DropDownList("ReportsTo", ViewBag.Users as SelectList, "Choose User", htmlAttributes: new { @class = "form-control" }) 

我需要获取下拉列表以在编辑视图中检索当前保存的值,并在索引和详细信息视图中显示GUID作为用户的名和姓。如果有人有替代解决方案,而不是尝试使用当前方法来完成它,我也很乐意尝试。

预先感谢:)

1 个答案:

答案 0 :(得分:0)

我设法解决了这个问题。它可能不是绝对最佳的解决方案,但似乎可行。这是下面的解决方案。我已将上面代码中的ReportsTo替换为解决方案中的SuperiorID。请注意,我的“身份用户”的ID带有整数,而不像默认的Identity实现那样带有GUID。

使用以下代码,我已将一个身份用户链接到另一个身份用户。

在我的身份模型中,我的ApplicationUser中有以下内容:Identity User类:

public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IUser<int>
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int? SuperiorID { get; set; }
        public string FullName
        {
            get
            {
                return FirstName + " " + LastName;
            }
        } 

        public async Task<ClaimsIdentity>
            GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager)
        {
            var userIdentity = await manager
                .CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }

        public virtual ApplicationUser Superior { get; set; }

    } 

我为上级创建了一个摘要,该摘要继承了身份用户,以便获得用户的ID和全名,这些ID和全名也放在了身份模型中:

public abstract class Superior : IdentityUser
    {

    } 

我在RegisterViewModel中添加了以下内容,以便在用户创建时添加上级:

public class RegisterViewModel
    {
        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        public string FullName
        {
            get
            {
                return FirstName + " " + LastName;
            }
        }

        [Display(Name = "Superior")]

        public virtual ApplicationUser Superior { get; set; }

    } 

我在EditUserViewModel中添加了以下内容,以便可以在编辑视图中编辑用户的上级:

public class EditUserViewModel
    {
        public int Id { get; set; }

        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        public string FullName
        {
            get
            {
                return FirstName + " " + LastName;
            }
        }

        [Display(Name = "Superior")]
        public int? SuperiorID { get; set; }

        public virtual ApplicationUser Superior { get; set; }

    } 

这是UserController的代码。我删除了与此无关的代码,并留下了一些代码来指示代码需要去的地方:

这出现在主类中:

private ApplicationDbContext db = new ApplicationDbContext(); 


public async Task<ActionResult> Index(int? SelectedSuperior)
        {
            var superiors = db.Users.OrderBy(s => s.FirstName).ToList();
            ViewBag.SelectedSuperior = new SelectList(superiors, "Id", "FullName", SelectedSuperior);
            int superiorID = SelectedSuperior.GetValueOrDefault();

            IQueryable<ApplicationUser> users = db.Users
                .Where(c => !SelectedSuperior.HasValue || c.SuperiorID == superiorID)
                .OrderBy(d => d.Id)
                .Include(d => d.Superior);
            var sql = users.ToString();

            return View(await UserManager.Users.ToListAsync());
        } 

public ActionResult Create()
        {
            PopulateSuperiorsDropDownList();
            return View();
        } 

public async Task<ActionResult> Create(RegisterViewModel userViewModel)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser
                {
                    FirstName = userViewModel.FirstName,
                    LastName = userViewModel.LastName,
                    SuperiorID = userViewModel.SuperiorID,
                };

            }
            PopulateSuperiorsDropDownList(userViewModel.SuperiorID);
            return View();
        } 

public async Task<ActionResult> Edit(int id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var user = await UserManager.FindByIdAsync(id);
            if (user == null)
            {
                return HttpNotFound();
            }

            var model = new EditUserViewModel()
            {
                Id = user.Id,
                FirstName = user.FirstName,
                LastName = user.LastName,
                SuperiorID = user.SuperiorID,
            };
            PopulateSuperiorsDropDownList(user.SuperiorID);
            return View(model);
        } 

public async Task<ActionResult> Edit([Bind(Include = "Email,Id,FirstName,LastName,SuperiorID")] EditUserViewModel editUser)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindByIdAsync(editUser.Id);
                if (user == null)
                {
                    return HttpNotFound();
                }

                // Update the User:
                user.Email = editUser.Email;
                user.FirstName = editUser.FirstName;
                user.LastName = editUser.LastName;
                user.SuperiorID = editUser.SuperiorID;
            }
            ModelState.AddModelError("", "Something failed.");
            PopulateSuperiorsDropDownList(editUser.SuperiorID);
            return View();
        } 

private void PopulateSuperiorsDropDownList(object selectedSuperior = null)
        {
            var superiorsQuery = from s in db.Users
                                   orderby s.FirstName + " " + s.LastName
                                   select s;
            ViewBag.SuperiorID = new SelectList(superiorsQuery, "Id", "FullName", selectedSuperior);
        } 

以下是创建和编辑视图的下拉列表,以便可以将上级分配给用户:

@Html.DropDownList("SuperiorID", null, "Choose Superior", htmlAttributes: new { @class = "form-control" }) 

要在详细信息页面中显示用户上级的全名,我使用以下代码:

@Html.TextBoxFor(m => m.Superior.FullName, new { @class = "form-control", @disabled = "disabled" }) 

要在索引页的数据表中显示用户上级的全名,我使用了以下方法:

<table class="table" id="users-table" width="100%">
                    <thead>
                        <tr>
                            <th title="First Name">
                                First Name
                            </th>
                            <th title="Last Name">
                                Last Name
                            </th>
                            <th title="Superior">
                                Superior
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var item in Model)
                        {
                            <tr>
                                <td>
                                    @Html.DisplayFor(modelItem => item.FirstName)
                                </td>
                                <td>
                                    @Html.DisplayFor(modelItem => item.LastName)
                                </td>
                                <td>
                                    @Html.DisplayFor(modelItem => item.Superior.FullName)
                                </td>
                            </tr>
                        }
                    </tbody>
</table>