[ASP.NET Core] Jak przekazac wartosc z widoku do modelu.

0

[Pytanie] - jak przekazac token z [HttpGet] do [HttpPost]
Przy restartowaniu hasla uzytkownik na meila dostaje link ktory zawiera token potrzebny do ustawienia nowego hasla. Nastepnie widok weryfikuje czy URL posiada odpowiednie wartosci i wyswietla strone

 [HttpGet]
 [AllowAnonymous]
        public IActionResult ResetPassword(string code = null)
        {
            if(code == null || userId == null)
            {
                throw new ApplicationException("Necessary informations are not provided.");
            }

            return View();
        }

Potrzebuje tego tokena w [HttpPost] zeby moc wyslac forme do SQL Server z nowym haslem.

[HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
        {


            if (!ModelState.IsValid)
            {
                return RedirectToAction(nameof(HomeController.Index));
            }

            var user = await _userManager.FindByEmailAsync(model.EmailAddress);

            if (user != null)
            {

                var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
                if (result.Succeeded)
                {
                    return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation));
                }

                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }

            }

            return View(model);
        }

Spotkalem sie z takim rozwiazaniem w dokumentacji AspNetCore, ale wartosc nie jest przekazywana i model.Code = null.

...
var model = new ResetPasswordViewModel { Code = code };
return View(model);

0

Akcja kontrolera ozdobiona atrybutem [HttpGet] powinna przygotować widok z formularzem, który miałby miejsce na kod z emaila. Kiedy użytkownik wyśle formularz z danymi to akcja kontrolera z atrybutem [HttpPost] powinna te dane obsłużyć.
Według mnie to wprowadzenie pomoże Ci zrozumieć o co chodzi. Zwróć uwagę na sposób sprawdzania poprawności modelu.
Ps. Rzucanie wyjątków w taki sposób to zła praktyka.

0

Dzieki za odpowiedz @Kokoniłaj, wybacz za slabe opisanie problemu, moj model wyglada nastepujaco:

public class ResetPasswordViewModel
    {

        public string Code { get; set; }

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

        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password {get; set;}

        [Required]
        [DataType(DataType.Password)]
        [Compare("Password", ErrorMessage ="Password and Confirm password fields should be the same.")]
        [Display(Name ="Confirm Password")]
        public string ConfirmPassword { get; set; }
    }

Natomiast odnosnie ww. wspomnianego tokena, znajduje sie on w URL, tak wyglada akcja kontrolera wysylajaca email'a do uzytkownika:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
        public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
        {
            ViewData["ReturnUrl"] = null;
            _logger.LogInformation("Started process of recovering password");
            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByEmailAsync(model.EmailAddress);
                if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
                {
                    _logger.LogInformation($"User with associated emial address: {model.EmailAddress} does not exists in the database" +
                        $"or email is not confirmed.");

                    //Don't reveal that the user does not exist or is not confirmed
                    return RedirectToAction(nameof(AccountController.ForgotPasswordConfirmation));
                }


                var code = await _userManager.GeneratePasswordResetTokenAsync(user);
                    **var callbackUrl = Url.Action(
                    action: nameof(AccountController.ResetPassword),
                    controller: "Account",
                    values: new { userId = user.Id, code = code },
                    protocol: Request.Scheme);**

                await _emailSender.SendEmailAsync(model.EmailAddress, "Reset Password",
                   $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");

                _logger.LogInformation($"Emial has been sent to {model.EmailAddress}");
                return RedirectToAction(nameof(ForgotPasswordConfirmation));
            }

            // If we got this far, something failed, re-display form
            return View(model);
        }

Forma z ResetPassword ([HttpPost]) obsluguje tylko wprowadzenie nowego Hasla przez uzytkownika, niestety nie umie przekazac tokena z czesci

var callbackUrl = Url.Action(
                    action: nameof(AccountController.ResetPassword),
                    controller: "Account",
                    values: new { userId = user.Id, code = code }, //Z tej czesci
                    protocol: Request.Scheme);

do

var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password); //Do tej czesci
1

Możesz uzupełnić model przekazywany do widoku o pole z kodem. Możesz nawet to pole ukryć. W akcji kontrolera przygotowującej widok na nowe hasło/email możesz pobrać ten kod tak jak tutaj z query stringa - FromQuery

1 użytkowników online, w tym zalogowanych: 0, gości: 1