13

I've found this answer but it doesn't seem to fit in my ASP Net Core project.

Things I am trying to understand:

  • How can I add a custom role. I've even looked directly in my MySQL database (table aspnetroles), but I don't know what to use as Id and ConcurrencyStamp.
  • Where do I put the code to seed the database with these new roles: in Startup? in Register under AccountController?
  • How do I tie this new role to a user? I've even looked through the tables and I don't know how to assign the data (there is no user2role or aspnetusers.role_id).
Community
  • 1
  • 1
Xavier Peña
  • 7,399
  • 9
  • 57
  • 99

3 Answers3

28

You could do this easily by creating a CreateRoles method in your startup class. This helps check if the roles are created, and creates the roles if they aren't; on application startup. Like so.

private async Task CreateRoles(IServiceProvider serviceProvider)
    {
        //adding customs roles : Question 1
        var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        string[] roleNames = { "Admin", "Manager", "Member" };
        IdentityResult roleResult;

        foreach (var roleName in roleNames)
        {
            var roleExist = await RoleManager.RoleExistsAsync(roleName);
            if (!roleExist)
            {
                //create the roles and seed them to the database: Question 2
                roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
            }
        }

        //Here you could create a super user who will maintain the web app
        var poweruser = new ApplicationUser
        {
            UserName = Configuration["AppSettings:UserName"],
            Email = Configuration["AppSettings:UserEmail"],
        };

        string userPWD = Configuration["AppSettings:UserPassword"];
        var _user = await UserManager.FindByEmailAsync(Configuration["AppSettings:AdminUserEmail"]);

       if(_user == null)
       {
            var createPowerUser = await UserManager.CreateAsync(poweruser, userPWD);
            if (createPowerUser.Succeeded)
            {
                //here we tie the new user to the role : Question 3
                await UserManager.AddToRoleAsync(poweruser, "Admin");

            }
       }
    }

and then you could call the await CreateRoles(serviceProvider); method from the Configure method in the Startup class. ensure you have IServiceProvider as a parameter in the Configure class.

Edit: If you're using ASP.NET core 2.x, my article here provides a much detailed experience. here

Temi Lajumoke
  • 2,350
  • 1
  • 14
  • 14
  • That looks like it! I'll try to implement it when I get home, I'll mark it as "answered" as soon as I test it in my code. About "Where do I put the code": I presume I should call it at the end of the `Configure` method in `Startup.cs`? – Xavier Peña Feb 13 '17 at 13:36
  • 1
    Thanks, Xavier. Yes, you can call it at the end of the `Configure` method. Right after configuring routes. – Temi Lajumoke Feb 13 '17 at 13:50
  • 16
    That was it, thank you very much. Marking it as answered. Just a quick note, since there were some steps that were not trivial for me (in case it can help someone else): in order to call your function from the bottom of the `Configure` method, I did it like so: `var serviceProvider = app.ApplicationServices.GetService(); CreateRoles(serviceProvider).Wait();`. – Xavier Peña Feb 15 '17 at 10:56
  • To call the function at the end of `Configure` method just do it like `CreateRoles(serviceProvider).Wait();` but be sure that for parameter of `Configure` method to be `IServiceProvider serviceProvider`. For example: `Configure(/*other parameters*/, IServiceProvider serviceProvider)`. – Endri Aug 07 '19 at 07:03
  • 1
    @temilajumoke - your link is broken. 404. – Dave Sep 13 '20 at 23:12
8

In addition to Temi's detailed answer, remember to replace

 services.AddDefaultIdentity<IdentityUser>()
            .AddEntityFrameworkStores<DbContext>();

With

 services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<DbContext>();

Also, make sure that the types specified in AddIdentity<> is the same as the types called in serviceProvider.GetRequiredService<>

For the above, our types called in serviceProvider.GetRequiredService<> in Configure.cs would be

 var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
 var userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();

Another important thing to note is that since CreateRoles(IServiceProvider) (from Temi's answer) is an async method, to call it in Configure method (which return void), you can use CreateRoles(serviceProviderInstance).Wait(); Hope this helps.

Siderite Zackwehdex
  • 6,293
  • 3
  • 30
  • 46
elfico
  • 450
  • 1
  • 6
  • 13
4

Adding to Temi's answer and Xavier's comment to it, my experience with this was a little different using .

In order to get this working I had to add the IServiceProvider as a parameter of the Configure method to get an instance of it.

public void Configure(
    IApplicationBuilder App,
    IHostingEnvironment Env,
    ILoggerFactory LoggerFactory,
    IServiceProvider ServiceProvider
)
{
    /* trimmed */

    CreateRoles(ServiceProvider).Wait();
}
Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
derpasaurus
  • 397
  • 3
  • 13