简体   繁体   中英

How to create "RoleManager<IdentityRole>" in ASP.Net Core?

I am unable to use RoleManager in my application. I am trying to seed an Admin user in to a .NET Core web application, and I want this user to have a role called "canEdit". What I've got currently produces this error:

System.InvalidOperationException: 'No service for type 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]' has been registered.'

I have tried various ways of doing this. I have tried using Service Provider to do it, dependency injection, etc. but they all give the same error.

ServiceProvider in the Configure method of Startup.cs:

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();

var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
var scope = scopeFactory.CreateScope();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
DbInitializer dbi = new DbInitializer(roleManager);
dbi.Initialize(context, userManager);

DBInitializer Class:

Constructor:

private readonly RoleManager<IdentityRole> rm;

    public DbInitializer(RoleManager<IdentityRole> rm)
    {
        this.rm = rm;
    }

CreateAdmin method:

private async Task CreateAdmin(UserManager<ApplicationUser> userManager, ApplicationDbContext context)
    {
        IdentityResult ir;
        ir = await rm.CreateAsync(new IdentityRole("canEdit"));
        IdentityRole canEdit = new IdentityRole("canEdit");
        ApplicationUser admin = new ApplicationUser
        {
            UserName = "Member1@email.com"
        };
        if (context.Users.Where(u => u.UserName == admin.UserName).Count() == 0)
        {
            userManager.CreateAsync(admin, "Password123!").Wait();
            userManager.AddToRoleAsync(admin, "canEdit").Wait();
        }
    }

CreateUsers method:

private void CreateUsers(UserManager<ApplicationUser> userManager, ApplicationDbContext context)
    {

        CreateAdmin(userManager, context).Wait();

        ApplicationUser customer1 = new ApplicationUser
        {
            UserName = "Customer1@email.com"
        };
        if (context.Users.Where(u => u.UserName == customer1.UserName).Count() > 0)
        {
            userManager.CreateAsync(customer1, "Password123!").Wait();
        }

This repeats for customer2, 3, 4, 5. I can optimise this by removing the need to create an object which I may not need (in the case where the email exists), but I was trying to knock up this method and the CreateAdmin method quickly, then optimise later. Unfortunately I then ran in to an error which I have been unable to fix.

The end goal is for the DbInitializer class to seed 5 regular users, and 1 admin user with extra permissions/claims.

Do you have the Identity services registered? Also, I ran into issues when I used .Wait() instead of await.

  services.AddIdentity<ApplicationUser,IdentityRole>(options=>
        {
            options.User.RequireUniqueEmail = true;               
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = false;      

        })
            .AddDefaultTokenProviders()
            .AddDefaultUI()
            .AddRoles<IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();
        services.AddAuthorization();
        services.AddAuthentication();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); 

If this helps, here is how I seeded my Db.

  public SeedDataBase(IServiceProvider _serviceProvider, ApplicationDbContext _context)
    {
        serviceProvider = _serviceProvider;
        context = _context;

    }
    private IServiceProvider serviceProvider;
    private ApplicationDbContext context;
    private ApplicationUser superUser;

    public async Task Seed()
    {

        await CreateSuperUser();
        await SeedDb();
    }
    private async Task CreateSuperUser()
    {
        var _userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        var userExists = await _userManager.GetUsersInRoleAsync("FULLADMIN");

        if (userExists.Count() < 1)
        {
            var _roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
            var _signinManger = serviceProvider.GetRequiredService<SignInManager<ApplicationUser>>();

            superUser = new ApplicationUser()
            {
                UserName = "superuser@superuser.com",
                Email = "superuser@superuser.com",
                FirstName = "Super",
                LastName = "User",
                AccountCreationDate = DateTime.Now.ToShortDateString(),
                Access = ApplicationUser.Permissions.FullAdmin
            };
            var permissions = Enum.GetNames(typeof(ApplicationUser.Permissions));

            foreach (var s in permissions)
            {
                await _roleManager.CreateAsync(new IdentityRole(s));
            }
            await _userManager.CreateAsync(superUser, "SecureP@ssword1234");
            await _userManager.AddToRoleAsync(superUser, Enum.GetName(typeof(ApplicationUser.Permissions), superUser.Access));
        }
    }

that may help someone in the future , you have to use the await for the RoleManager.CreateAsync method

then to verify if the operation was compeleted successfully use

var res = await _roleManager.CreateAsync(new IdentityRole(Role));
  if(res.Succeeded)
  {
    return Ok("created successfully !");
  }    


               `

If you use IdentityServer4 or Duende.IdentityServer in .NET 5 < with Individual user accounts then edit Startup.cs . Look for the following values:

services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

Edit it to look like this:

services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM