2

On my website I use MVC Authentication, if a user wants to reset his password, he clicks on 'Forgot Password' then he gets by email a link with a unique code to reset his password.

My issue is if for some reason the reset fails (for example- password and password confirmation don't match etc) then it returns to the View without the unique code that was generated in the link that the user got by email and the reset password won't work afterwards (code query string param)

How can I keep the query string unique code when the reset fails and return it to the View?

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
      if (!ModelState.IsValid)
      {
           return View(model);
      }
      var user = await UserManager.FindByNameAsync(model.Email);
      if (user != null)
      {
           var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
           if (result.Succeeded)
           {
                return RedirectToAction("ResetPasswordConfirmation", "Account");
           }
      }
       ViewBag.Error = "Password reset failed";
       return View();
}

And this is the form:

  <form id="reset-form" method="post" action="Account/ResetPassword">
        @Html.AntiForgeryToken()
        <div class="header">
            <h2>Reset Password</h2>
            @if (!String.IsNullOrEmpty(ViewBag.Error))
            {
                <div class="invalid">
                    @ViewBag.Error
            </div>
            }
        </div>
        <div class="inputField">
            <input type="email" id="email" name="email" placeholder="USERNAME" />
        </div>
        <div class="inputField">
            <input type="password" id="password" name="password" placeholder="PASSWORD" />
        </div>
        <div class="inputField">
            <input type="password" id="confirm-password" name="confirmPassword" placeholder="CONFIRM PASSWORD" />
            <input type="submit"/>
        </div>
    </form>

I need it to return to the View like this:

~/account/resetpassword?code=xyz

2
  • What is the query string parameter named and what is the code used to post to this action method? Commented Jan 21, 2018 at 18:16
  • @NightOwl888 Please see my edited answer. Commented Jan 21, 2018 at 19:58

1 Answer 1

4

The URL will remain the same as what you post when the view is returned unless you do a redirect (not recommended).

However, the issue isn't that you need the URL to change after the action method runs. You need to change the URL that is posted to the action method to include the query string so it is there when the action method returns the view. This can be done by simply changing the URL of the form.

Note that you should never hard code the URL in MVC views. Instead, you should always use controller, action, and other route values to resolve the URL using the UrlHelper (and related extension methods such as ActionLink). The routing infrastructure should be the only place where URLs exist so they can be changed in one place.

In this case the solution is to use Html.BeginForm to build up the form tag based on routing.

@using (Html.BeginForm("ResetPassword", "Account", new { code = "xyz" }, FormMethod.Post))
{
    @Html.AntiForgeryToken()
    <div class="header">
        <h2>Reset Password</h2>
        @if (!String.IsNullOrEmpty(ViewBag.Error))
        {
            <div class="invalid">
                @ViewBag.Error
        </div>
        }
    </div>
    <div class="inputField">
        <input type="email" id="email" name="email" placeholder="USERNAME" />
    </div>
    <div class="inputField">
        <input type="password" id="password" name="password" placeholder="PASSWORD" />
    </div>
    <div class="inputField">
        <input type="password" id="confirm-password" name="confirmPassword" placeholder="CONFIRM PASSWORD" />
        <input type="submit"/>
    </div>
}

Of course, you shouldn't hard code "xyz" here either, it should be passed to the view from the HttpGet ResetPassword method either in a Model or in ViewBag.

Note that if the url parameter of the route definition (typically in RouteConfig.cs) does not contain a parameter for code, it will automatically be added to the URL as a query string parameter.

Sign up to request clarification or add additional context in comments.

1 Comment

Works perfectly, thank you very much for the answer and the great explanation!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.