How to get url parameter to my controller?

I’m making a function to reset the password of a user using ASP.NET Identity. However, the token is not being picked up in my controller. When I submit the form, it says

“The Token field is required.”

Why does it not pick up my token?
Following code is being used to generate the resetLink:

    var user = _userManager.FindByNameAsync(email).Result;

    if (user == null || !_userManager.IsEmailConfirmedAsync(user).Result)
    {
        ViewBag.Message = "Error while resetting your password!";
        return View("ResetPassword");
    }

    var token = _userManager.
          GeneratePasswordResetTokenAsync(user).Result;

    var resetLink = Url.Action("SetPassword",
                    "Auth", new { token },
                     protocol: HttpContext.Request.Scheme);

This generates the link: http://localhost:50015/adviseur/auth/setpassword?token=someverylongnumbers

This link goes to the following view, viewmodel and controller:
AuthController.cs

[HttpGet]
public IActionResult SetPassword()
{
    return View();
}

SetPassword.cshtml

@model SetPasswordModel

<h1>Set Your Password</h1>

<form asp-controller="Auth"
      asp-action="RequestNewPassword"
      method="post">

    <input type="hidden" asp-for="Token" />
    <table>
        <tr>
            <td><label asp-for="UserName"></label></td>
            <td><input asp-for="UserName" /></td>
        </tr>
        <tr>
            <td>
                <label asp-for="Password">
                    New Password
                </label>
            </td>
            <td><input asp-for="Password" /></td>
        </tr>
        <tr>
            <td>
                <label asp-for="ConfirmPassword">
                    Confirm New Password
                </label>
            </td>
            <td><input asp-for="ConfirmPassword" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit"
                       value="Reset Password" />
            </td>
        </tr>
    </table>

    <div asp-validation-summary="All"></div>

</form>

SetPasswordModel.cs:

#region Using

using System.ComponentModel.DataAnnotations;

#endregion

namespace x.Areas.Adviseur.ViewModels
{
    public class SetPasswordModel
    {
        [Required]
        public string UserName { get; set; }
        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }
        [Required]
        [DataType(DataType.Password)]
        public string ConfirmPassword { get; set; }
        [Required]
        public string Token { get; set; }
    }
}

The form makes the request to the following controller:

[HttpPost]
public IActionResult RequestNewPassword(SetPasswordModel obj)
{
    User user = _userManager.FindByNameAsync(obj.UserName).Result;
    IdentityResult result = _userManager.ResetPasswordAsync(user, obj.Token, obj.Password).Result;

    if (result.Succeeded)
    {
        ViewBag.Message = "Password reset successful!";
        return View("Login");
    }
    else
    {
        ViewBag.Message = "Error while resetting the password!";
        return View("SetPassword");
    }
}

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

the token is not being picked up in my controller

That is because you haven’t send it. You are not collecting the token from the url to use it on the next step. Therefore, at the RequestNewPassword action method, the model binder cannot find a value in the Token form-field, and it cannot create a SetPasswordModel object without a value for the Token property because you have marked it as Required. Hence the complain –

“The Token field is required.”

At your SetPassword action method –

  1. Add a string parameter named token to the method, so that the model binder can collect the token string from the url
  2. Pass the token to the view through the ViewBag or the model.
[HttpGet]
public IActionResult SetPassword(string token)
{
    ViewBag.Token = token;
    return View();

    // OR,
    // var model = new SetPasswordModel { Token = token };
    // return View(model);
}

If you pass the token through the model, then no change is needed in the view. But if you pass it through the ViewBag, then set it to the Token form-field –

<input type="hidden" asp-for="Token" value="@ViewBag.Token" />

Now, when you submit the form, at RequestNewPassword action method, the model binder will be able to create a SetPasswordModel object for you without complaining.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x