ASP.NET Core How to get UserManager working in controller?

Viewed 6094

I want to use UserManager in my web app. The app's being built with asp.net core 3.0.
I need to get users with a given role(let's say CustomerRole) with own controller. Normally, I would use this:

public class CustomerController : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly UserManager<ApplicationUser> _userManager;

    public CustomerController(IUnitOfWork unitOfWork, UserManager<ApplicationUser> userManager)
    {
        _unitOfWork = unitOfWork;
        _userManager = userManager;
    }

    public IActionResult OnGet()
    {
        return Json(new { data = _userManager.GetUsersInRoleAsync("CustomerRole").Result });
    }
}

And this code returns error 500. UserManager is not initialized either.
I've checked that using code below works as intended. However, I can't get users with a specific role. That's not want I want to achieve.

public class CustomerController : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly UserManager<ApplicationUser> _userManager;

    public CustomerController(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    [HttpGet]
    public IActionResult OnGet()
    {
        return Json(new { data = _unitOfWork.Customer.GetAll() });
    }
}

Here's ApplicationUser code:

public class ApplicationUser : IdentityUser, IApplicationUser
{
    [Display(Name = "Full name")]
    public string FirstName { get; set; }

    public string LastName { get; set; }

    [NotMapped]
    public string FullName => $"{FirstName} {LastName}";
}

And ConfigureServices method from Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddDefaultTokenProviders()
        .AddEntityFrameworkStores<ApplicationDbContext>();


    services.AddScoped<IUnitOfWork, UnitOfWork>();
    services.AddSingleton<IEmailSender, EmailSender>();

    services.AddMvc(options => options.EnableEndpointRouting = false)
        .SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_3_0);

    services.AddControllersWithViews();

    services.AddRazorPages().AddRazorRuntimeCompilation();
}

@Update
Solution found. In ConfigureServices() method I fixed the typo, as mvermef instructed. That was big help, really. After that, I changed in _LoginPartial.cshtml the following:

@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

to:

@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

At this point application was running and I was able to use UserManager<> however I wanted. I quickly found out that an user wouldn't be able to register or log in. The soulution was that change(from to :

    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;

Remember to make the change in constructors too. I changed every file in Areas(default name) directory.

2 Answers

Looks like you got a typo in your ConfigureServices()

services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()   //<<<<<< You have IdentityUser
        .AddDefaultTokenProviders()
        .AddEntityFrameworkStores<ApplicationDbContext>();

Because you have IdentityUser instead of your derived type it will throw an error... You don't need to use AddScoped

Add this to ConfigureServices method

services.AddScoped<UserManager<ApplicationUser>>();
Related