C-Scholl20
C-Scholl20

Reputation: 377

AspNetCore.Identity Reset Password - Instance of 'X' cannot be tracked

I'm trying to implement a password reset mechanism using the AspNetCore.Identity assembly. It starts with a user saying they forgot their password, entering their email and password, then submitting. That ends up calling this code

IdentUser user = UserManager.FindByName(passwordObj.username);

//Some unrelated code in between

Task<string> codeTask = UserManager.GeneratePasswordResetTokenAsync(user);

string code = Base64ForUrlEncode(codeTask.Result);
string applicationUrl = string.Format("{0}/{1}?userId={2}&&token={3}", ApplicationUrl, "ResetPasswordView", user.Id, code);

I don't have any issues generating a reset password token, the task runs to completion and I get an email with the correct URL.

However, when I try resetting the password, I get to this chunk of code

public JsonResult ResetPassword(ResetPasswordModel passwordObj)
{
    IdentUser User = UserManager.FindById(passwordObj.userId);

    //Unrelated code

    Task<IdentityResult> resetPassTask = UserManager.ResetPasswordAsync(User, Base64ForUrlDecode(passwordObj.token), passwordObj.resetPassword);
    IdentityResult user = resetPassTask.Result;

....
}

and the resetPassTask.Result line is generating a an exception saying "The instance of entity type 'IdentUser' cannot be tracked because another instance of this type with the same key is already being tracked.

I'm still relatively new to ASP.NET Core and am just starting to learn the ins and outs of async calls, so I'm having a tough time debugging this. I've search SO for answers and haven't found anything that's fixed my issue, so here I am. Any idea on how to fix or debug this issue?

Upvotes: 1

Views: 767

Answers (1)

C-Scholl20
C-Scholl20

Reputation: 377

So, I figured out my issue, and am posting my fix so that hopefully others facing this issue can be helped.

My FindById function was implemented in an extension of the AspNetCore.Identity's UserManager, IdentUserManager. FindById is not asynchronous ->

public IdentUser FindById(int userId)
    {
        return _dbContext.Users.Include(user => user.IdentUserProfile)
            .Include(role => role.IdentUserProfile.IdentUserOrgRole)
            .Include(client => client.IdentUserProfile.IdentMapApplicationsWithUser).FirstOrDefault(x => x.Id == userId);
    }

So instead, I am now using AspNetCore.Identity's FindByIdAsync

IdentUser User = await UserManager.FindByIdAsync(passwordObj.userId.ToString());

and that fixed my issue. Not completely sure what the reason is, but using DbContexts directly and asynchronous calls don't seem to mix well. Feel free to comment with any explanations

Upvotes: 2

Related Questions