Search code examples
asp.net-coreasp.net-identity

CreateAsync doesn't save IdentityUser to database with derived IdentityUser


When Posting the following code works fine until it reaches the _userManager.CreateAsync method. No data is saved to the database.

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private readonly ApplicationDbContext _appDbContext;

    private readonly UserManager<IdentityUser> _userManager;

    public ValuesController(UserManager<IdentityUser> userManager, ApplicationDbContext appDbContext)
    {
        _userManager = userManager;
        _appDbContext = appDbContext;
    }

    [HttpPost]
    public async Task<IActionResult> Post()
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        AppUser user = new AppUser();
        user.Email = "[email protected]";
        user.FirstName = "mark";
        user.LastName = "Macneill";
        user.UserName = "Saints22";
        await _userManager.CreateAsync(user, "P4$$word");

        return new OkObjectResult("Account created");

    }

    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

Solution

  • You don't seem to be using the IdentityUser directly but instead a AppUser class. This might be a class extending IdentityUser<> or IdentityUser. I am not sure if you have the rest of your setup right, so here is the process:

    If you have created a custom AppUser class, let's say you created it as follows:

    class AppUser : IdentityUser<int>
    

    This would mean you have assigned the primary key as in int. However, if you extended IdentityUser instead, note that IdentityUser extends IdentityUser<string>, meaning your key is a string. Going ahead I am going to assume your key is int. If not, you can make the changes accordingly (change all ints to your key type.

    In your startup class, you need to be adding the following to register this as your user class used for Identity

    services.AddIdentity<AppUser, IdentityRole<int>>()
            .AddEntityFrameworkStores<ApplicationDbContext>();
    

    Your ApplicationDbContext needs to be defined as follows:

    public class ApplicationDbContext : IdentityDbContext<AppUser, IdentityRole<int>, int>
    

    If you don't want to use IdentityRole<int> in the above two pieces of code, you can define a custom role class as follows:

    public AppUserRole : IdentityRole<int>
    

    Once you have these setup, you need to inject UserManager<AppUser> not UserManager<IdentityUser>.