skip to Main Content

I am making a panel where the website admins can access users’ account data and change stuff. For example, name, email, username, etc…
I want when the admin changes the email on his computer it will not change the email in the database unless the user confirms it in his new email. I have the registration functions and I kind of used them but with them, I can’t change the Email After it clicked, only before. Here’s the code, hope you can help me find a way to do this.

    [HttpPost]
    public async Task<IActionResult> EditUser(EditUserModel model, string returnUrl = null)
    {
        var user = await userManager.FindByIdAsync(model.Id);

        var _user = user;

        _user.UserName = model.UserName;
        _user.EmailConfirmed = false;
        _user.FirstName = model.FirstName;
        _user.LastName = model.LastName;

        if (user == null)
        {
            ViewBag.ErrorMessage = $"User with Id: {model.Id} cannot be found";
            return View("NotFound");
        }
        else
        {
            if (user.Email != model.Email)
            {

                returnUrl ??= Url.Content("~/");

                var result = await userManager.UpdateAsync(_user);

                if (result.Succeeded)
                {
                    var code = await userManager.GenerateEmailConfirmationTokenAsync(_user);
                    code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                    var callbackUrl = Url.Page(
                        "/Account/ConfirmEmail",
                        pageHandler: null,
                        values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
                        protocol: Request.Scheme);

                    await _emailSender.SendEmailAsync(model.Email, "Confirm your email",
                        $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

                    /*
                    if (NewEmailConfirmed) --> the if statement that supposes to check if the user confirmed his new email
                    {
                        _user.Email = model.Email;
                        await userManager.UpdateAsync(_user);
                    }
                    */
                }

              
            }
            else //If the admin updated anything but the Email.
            {
                user.UserName = model.UserName;
                user.FirstName = model.FirstName;
                user.LastName = model.LastName;

                var result = await userManager.UpdateAsync(user);

                if (result.Succeeded)
                    return RedirectToAction("ListUsers");

                foreach (var error in result.Errors)
                    ModelState.AddModelError("", error.Description);

                return View(model);
            }

        }
        return RedirectToAction("ListUsers");
    }

2

Answers


  1. Chosen as BEST ANSWER

    So, After some research, I found that in the "Add new scaffold item" you can add the checkbox called "AccountManageEmail". After I added it, when I clicked on my username it opened some user settings and I could change My email. So I took the code from there and after some debugging I found the code below to work 100%.

    Controller

    private UserManager<ApplicationUser> userManager;
    private readonly IEmailSender _emailSender;
    private readonly ILogger logger;
    
    public AdministrationController(UserManager<ApplicationUser> userManager,
                                        IEmailSender emailSender,
                                        ILogger<AdministrationController> logger)
        {
            this.userManager = userManager;
            _emailSender = emailSender;
            this.logger = logger;
        }
    
        public string Username { get; set; }
    
        public string Email { get; set; }
    
        public bool IsEmailConfirmed { get; set; }
    
        [TempData]
        public string StatusMessage { get; set; }
    
        [BindProperty]
        public InputModel Input { get; set; }
    
        public class InputModel
        {
            [EmailAddress]
            [Display(Name = "New email")]
            public string NewEmail { get; set; }
        }
    
        private async Task LoadAsync(ApplicationUser user)
        {
            var email = await userManager.GetEmailAsync(user);
            Email = email;
    
            Input = new InputModel
            {
                NewEmail = email,
            };
    
            IsEmailConfirmed = await userManager.IsEmailConfirmedAsync(user);
        }
    
        public async Task<IActionResult> OnGetAsync()
        {
            var user = await userManager.GetUserAsync(User);
            if (user == null)
            {
                return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'.");
            }
    
            await LoadAsync(user);
            return RedirectToAction("ListUsers", "Administration");
        }
    
        [HttpPost]
        public async Task<IActionResult> ChangeEmail(EditUserModel model)
        {
            var user = await userManager.FindByIdAsync(model.Id);
            if (user == null)
            {
                return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'.");
            }
    
            //if (!ModelState.IsValid)
            //{
            //    await LoadAsync(user);
            //    return RedirectToAction("ListUsers", "Administration");
            //}
    
            var email = await userManager.GetEmailAsync(user);
            if (Input.NewEmail != email && Input.NewEmail != null)
            {
                var userId = await userManager.GetUserIdAsync(user);
                var code = await userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail);
                code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmailChange",
                    pageHandler: null,
                    values: new { area = "Identity", userId = userId, email = Input.NewEmail, code = code },
                    protocol: Request.Scheme);
                await _emailSender.SendEmailAsync(
                    Input.NewEmail,
                    "Confirm your email",
                    $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
    
                StatusMessage = "Confirmation link to change email sent. Please check your email.";
                return RedirectToAction("ListUsers", "Administration");
            }
    
            StatusMessage = "Your email is unchanged.";
            return View(model);
        }
    
        [HttpPost]
        public async Task<IActionResult> EditUser(EditUserModel model) 
        {
            var user = await userManager.FindByIdAsync(model.Id);
    
            if (user == null)
                return NotFound($"User with Id: {model.Id} cannot be found.");
    
            user.UserName = model.UserName;
            user.FirstName = model.FirstName;
            user.LastName = model.LastName;
    
            var result = await userManager.UpdateAsync(user);
    
            if (result.Succeeded)
            {
                if (user.Email != Input.NewEmail)
                    await ChangeEmail(model);
                return RedirectToAction("ListUsers");
            }
    
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError("", error.Description);
            }
    
            return View(model);
        }
    

    Model

    public class EditUserModel
    {
        [BindProperty]
        public InputModel Input { get; set; }
    
        public class InputModel
        {
            [EmailAddress]
            [Display(Name = "New email")]
            public string NewEmail { get; set; }
        }
    }
    

    View

    @model SvivaTeamVersion3.Models.EditUserModel
    <form method="post">
        <div class="form-group row"> @*Display the current Email*@
            <label asp-for="Email" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Email" disabled class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
        </div>
    
        <div class="form-group row"> @*Change to a new Email*@
            <label asp-for="Input.NewEmail" class="col-sm-2 col-form-label"></label>
            <div class="col-sm-10">
                <input asp-for="Input.NewEmail" id="newMail" class="form-control" />
            </div>
        </div>
    
     <div asp-validation-summary="All" class="text-danger"></div>
    
    </form>
    
    @section Scripts {
        <partial name="_ValidationScriptsPartial" />
    }
    

    After all

    If you have done everything correctly you should have an input box to change the Email. When you change your Email a new Email will be sent to you in your new mail. (only if you have done Email confirmation) If you would click on it the Email will change.


  2. I think you should add a "confirmation" flag of the bool type in the database, in the user table. Thus, you can know if the registration needs some kind of validation.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search