Search code examples
c#asp.netentity-frameworkasp.net-mvc-5asp.net-identity-2

How to Update Identity's Manage Controller


This is the default Manage Controller in AccountController.cs

  public async Task<ActionResult> Manage(ManageUserViewModel model)
        {
            bool hasPassword = HasPassword();
            ViewBag.HasLocalPassword = hasPassword;
            ViewBag.ReturnUrl = Url.Action("Manage");
            if (hasPassword)
            {
                if (ModelState.IsValid)
                {
                    IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
                    }
                    else
                    {
                        AddErrors(result);
                    }
                }
            }
            else
            {
                ModelState state = ModelState["OldPassword"];
                if (state != null)
                {
                    state.Errors.Clear();
                }

                if (ModelState.IsValid)
                {
                    IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
                    }
                    else
                    {
                        AddErrors(result);
                    }
                }
            }

            return View(model);
        }

This currently updates the password. But what if I want to change model's username? How can I modify this code? I know some programming but I have no idea to modify this code? I welcome any help. Thanks.


Solution

  • That action looks specific to changing a password. I would create a different action and view to modify the other fields you want to change like username, email, etc. The table Users is available through the identity context so you could follow the typical pattern of setting up the Get, View and Post:

    First make a viewmodel of what you want to allow editing on:

    public class UserUpdateViewModel
    {
        [Required]
        [MaxLength(50)]
        public string UserName { get; set; }
    
        [Required]
        [MaxLength(50)]
        public string FirstName { get; set; }
    
        [Required]
        [MaxLength(50)]
        public string LastName { get; set; }
    
        [Required]
        [EmailAddress]
        [MaxLength(255)]
        public string Email { get; set; }
    }
    

    Then create the Get action:

        [HttpGet]
        public ActionResult Edit(string id, ManageMessageId? message = null)
        {
            var user = _db.Users.First(u => u.UserName == id);
            // move entity fields to viewmodel from constructor, automapper, etc.        
            var model = new UserUpdateViewModel 
            {
                UserName = user.UserName,
                FirstName = user.FirstName,
                LastName = user.LastName,
                Email = user.Email
            };  
            ViewBag.MessageId = message;
            return View(model);
        }
    

    Then make a view followed by the Post:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit(UserUpdateViewModel userUpdateViewModel)
        {
            if (!ModelState.IsValid) return View(userUpdateViewModel);
    
            var user = _db.Users.First(u => u.UserName == userUpdateViewModel.UserName);
            // Mapper.Map(userUpdateViewModel, user);  // move viewmodel to entity model
            // instead of automapper, you can do this:
            user.UserName = userUpdateViewModel.UserName;
            user.FirstName = userUpdateViewModel.FirstName;
            user.LastName = userUpdateViewModel.LastName;
            user.Email = userUpdateViewModel.Email;
    
            await _db.SaveChangesAsync();
    
            return this.RedirectToAction(a => a.Index()).WithSuccess("User updated.");
        }