Search code examples
c#asp.net.netasp.net-identity

Unable to resolve service for type 'Microsoft.AspNetCore.Identity.RoleManager`


I writing code for adding roles to users in my asp.net core project

Here is my Roles controller.

public class RolesController : Controller
{
    RoleManager<IdentityRole> _roleManager;
    UserManager<AspNetUsers> _userManager;
    public RolesController(RoleManager<IdentityRole> roleManager, UserManager<AspNetUsers> userManager)
    {
        _roleManager = roleManager;
        _userManager = userManager;
    }
    public IActionResult Index() => View(_roleManager.Roles.ToList());

    public IActionResult Create() => View();
    [HttpPost]
    public async Task<IActionResult> Create(string name)
    {
        if (!string.IsNullOrEmpty(name))
        {
            IdentityResult result = await _roleManager.CreateAsync(new IdentityRole(name));
            if (result.Succeeded)
            {
                return RedirectToAction("Index");
            }
            else
            {
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }
        }
        return View(name);
    }

    [HttpPost]
    public async Task<IActionResult> Delete(string id)
    {
        IdentityRole role = await _roleManager.FindByIdAsync(id);
        if (role != null)
        {
            IdentityResult result = await _roleManager.DeleteAsync(role);
        }
        return RedirectToAction("Index");
    }

    public IActionResult UserList() => View(_userManager.Users.ToList());

    public async Task<IActionResult> Edit(string userId)
    {
        // получаем пользователя
        AspNetUsers user = await _userManager.FindByIdAsync(userId);
        if(user!=null)
        {
            // получем список ролей пользователя
            var userRoles = await _userManager.GetRolesAsync(user);
            var allRoles = _roleManager.Roles.ToList();
            ChangeRoleViewModel model = new ChangeRoleViewModel
            {
                UserId = user.Id,
                UserEmail = user.Email,
                UserRoles = userRoles,
                AllRoles = allRoles
            };
            return View(model);
        }

        return NotFound();
    }
    [HttpPost]
    public async Task<IActionResult> Edit(string userId, List<string> roles)
    {

        AspNetUsers user = await _userManager.FindByIdAsync(userId);
        if(user!=null)
        {

            var userRoles = await _userManager.GetRolesAsync(user);

            var allRoles = _roleManager.Roles.ToList();

            var addedRoles = roles.Except(userRoles);

            var removedRoles = userRoles.Except(roles);

            await _userManager.AddToRolesAsync(user, addedRoles);

            await _userManager.RemoveFromRolesAsync(user, removedRoles);

            return RedirectToAction("UserList");
        }

        return NotFound();
    }
}

But when I run app and going to Roles controller. I get this error

An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]' while attempting to activate 'VchasnoCrm.Controllers.RolesController'. Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

How I can fix this?


Solution

  • In Net Core 3.1 there are two different overload of ASP.NET Core Identity, first version named DefaultIdentity, You have not opportunity to set simultaneously User and Roles, so syntax look as

    services.AddDefaultIdentity<IdentityUser>(options => ...
    

    Second version of Identity use User and Roles and look as

    services.AddIdentity<IdentityUser, IdentityRole>(options => ...
    

    It's different version of identity, first include IdentityUI, second not include IdentityUI. But, you CAN include roles to first version, if you add Roles services as

    services.AddDefaultIdentity<IdentityUser>(options =>...).AddRoles<IdentityRole>()...
    

    If you have included Roles services to your set of services, you can inject Roles to Configure method as

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DbContextOptions<ApplicationDbContext> identityDbContextOptions, UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)
    

    this error message usually appear if you inject

    RoleManager<IdentityRole> roleManager
    

    in any place of your project without adding IdentityRole services (by first or second way).