1

I have the following code to reset the password of a user (who actually does not have a password):

ApplicationUser u1 =  _userManager.FindByEmailAsync("aclowneyb8@un.org").Result;
string resetToken1 = _userManager.GeneratePasswordResetTokenAsync(u1).Result;
IdentityResult r1 = _userManager.ResetPasswordAsync(u1, resetToken1, "12345Da*").Result;

r1 returns succeed but the password is indeed not changed. I cannot login with the new password. Any suggestions? What I am missing?

Tony Ngo
  • 19,166
  • 4
  • 38
  • 60
renakre
  • 8,001
  • 5
  • 46
  • 99
  • What an awful way to set a password. Have a look at [this answer](https://stackoverflow.com/questions/29291366/asp-net-identity-change-password/29291561#29291561) its bit older and for ASP.NET Identity 2.x, but should apply to .NET Core too with little to no changes and it changes the password in one single transaction. P.S. using `.Result` is awful too. `await` it properly :) – Tseng Sep 05 '19 at 13:47
  • Thanks @Tseng then when do we need `.Result`? – renakre Sep 05 '19 at 13:54
  • Never. Use `await` with async methods, i.e. `var ul = await _userManager.FindByEmailAsync(...);`. By calling `Result`, you're blocking the thread. – Chris Pratt Sep 05 '19 at 13:56
  • Ideally never. It basically forces async code to be executed in async, which can create all kind of troubles (depending where you develop on, WPF, Desktop, Console, ASP.NET Core or ASP.NET (the legacy one) - not all of these may deadlock, since it depends on the used synchronization context) – Tseng Sep 05 '19 at 13:56
  • @Tseng then why does it even exists :) – renakre Sep 05 '19 at 13:58
  • Legacy reasons and so you can start and await legacy code in `void Main(...)` :P It also has different exception throw behaviour, but its off-topic. Use google or stack overflow search to find out why its bad – Tseng Sep 05 '19 at 13:59
  • @renakre it's not legacy reasons. It's meant to be used when you *do* want to block, or when you know the task is already finished. In a `ContinueWith` for example, you know that the task is already finished. – Panagiotis Kanavos Sep 05 '19 at 14:42

1 Answers1

1

You should use async and await in this case to execute your code

Below is my example

[HttpPost("ResetPassword"), ValidModel, AllowAnonymous]
public async Task<IActionResult> ResetPassword([FromBody]ResetPasswordViewModel model)
{
    if (string.IsNullOrEmpty(model.Token) || string.IsNullOrEmpty(model.Email))
    {
        return RedirectToAction("Index", "Error", new { statusCode = AppStatusCode.NotFound });
    }

    var isResetTokenValid = await _userManager.CheckValidResetPasswordToken(model.Token, model.Email);

    if (!isResetTokenValid || string.IsNullOrEmpty(model.Email))
    {
        return StatusCode(AppStatusCode.ResetPassTokenExpire);
    }

    var user = await _userManager.FindByEmailAsync(model.Email);
    if (user == null)
    {
        return Ok();
    }

    await _userManager.ResetPasswordAsync(user, model.Token, model.Password); // use await here
    return Ok();
}
Tony Ngo
  • 19,166
  • 4
  • 38
  • 60