89

There is very little documentation about using the new Asp.net Identity Security Framework.

I have pieced together what I could to try and create a new Role and add a User to it. I tried the following: Add role in ASP.NET Identity

which looks like it may have gotten the info from this blog: building a simple to-do application with asp.net identity and associating users with to-does

I have added the code to a Database Initializer that is run whenever the model changes. It fails on the RoleExists function with the following error:

System.InvalidOperationException occurred in mscorlib.dll The entity type IdentityRole is not part of the model for the current context.

protected override void Seed (MyContext context)
{
    var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context)); 
    var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

    // Create Admin Role
    string roleName = "Admins";
    IdentityResult roleResult;

    // Check to see if Role Exists, if not create it
    if (!RoleManager.RoleExists(roleName))
    {
        roleResult = RoleManager.Create(new IdentityRole(roleName));
    }
}

Any help is appreciated.

Community
  • 1
  • 1
colbyJax
  • 1,033
  • 1
  • 9
  • 9

11 Answers11

78

Here we go:

var roleManager = new RoleManager<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));


   if(!roleManager.RoleExists("ROLE NAME"))
   {
      var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
      role.Name = "ROLE NAME";
      roleManager.Create(role);

    }
Piotr Stulinski
  • 9,241
  • 8
  • 31
  • 46
  • 2
    This helped me, especially since I wasn't using Migrations. I am using DropCreateDatabaseAlways. – J86 Feb 26 '15 at 10:53
  • My problem was that I was using the wrong context. I had created two connection strings, one called `IdentityDbContext` and another one I was using a custom context, so when I used your suggestion `AppilcationDbContext()`, it worked. – megamaiku Oct 02 '17 at 23:45
  • var roleManager = new RoleManager(new RoleStore(db)); – Nour Lababidi Oct 10 '18 at 20:59
26

Verify you have following signature of your MyContext class

public class MyContext : IdentityDbContext<MyUser>

Or

public class MyContext : IdentityDbContext

The code is working for me, without any modification!!!

jd4u
  • 5,789
  • 2
  • 28
  • 28
  • 4
    Thanks everyone for your replies. Everything is working now. Checking the Context led me in the right direction. When asp.net identity is created, it creates a new context (ApplicationDbContext) which extends IdentityDbContext. In my code, I was referencing my original context which did not extend IdentityDbContext. If someone else has this issue, check your contexts and double check your APP_DATA directory to make sure you are not accidently creating two databases. – colbyJax Oct 31 '13 at 17:37
26

Here is the complete article describing how to create roles, modify roles, delete roles and manage roles using ASP.NET Identity. This also contains the User interface, controller methods, etc.

http://www.dotnetfunda.com/articles/show/2898/working-with-roles-in-aspnet-identity-for-mvc

Web Developer
  • 333
  • 4
  • 17
Sheo Narayan
  • 1,196
  • 2
  • 14
  • 17
  • 1
    Your blog is nice, but out of date, can you update the account controller – aggie Jan 23 '16 at 10:15
  • Its already for ASP.NET MVC 5 (What update you are looking for aggie?). You can download the source code from GitHub link specified in the article. – Sheo Narayan Jan 27 '16 at 06:58
  • 1
    Some of those functions seem deprecated from 2.2.0 in the latest. 1) can I use the same code in the current version 2) how can I change the primary key from Guid to email 3) any recommendations on how to integrate recpatcha with Identity would be appreciated http://j.mp/1nohaHe – aggie Jan 27 '16 at 18:36
15

In ASP.NET 5 rc1-final, I did following:

Created ApplicationRoleManager (in similar manner as there is ApplicationUser created by template)

public class ApplicationRoleManager : RoleManager<IdentityRole>
{
    public ApplicationRoleManager(
        IRoleStore<IdentityRole> store,
        IEnumerable<IRoleValidator<IdentityRole>> roleValidators,
        ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors,
        ILogger<RoleManager<IdentityRole>> logger,
        IHttpContextAccessor contextAccessor)
        : base(store, roleValidators, keyNormalizer, errors, logger, contextAccessor)
    {
    }
}

To ConfigureServices in Startup.cs, I added it as RoleManager

services.
    .AddIdentity<ApplicationUser, IdentityRole>()
    .AddRoleManager<ApplicationRoleManager>();

For creating new Roles, call from Configure following:

public static class RoleHelper
{
    private static async Task EnsureRoleCreated(RoleManager<IdentityRole> roleManager, string roleName)
    {
        if (!await roleManager.RoleExistsAsync(roleName))
        {
            await roleManager.CreateAsync(new IdentityRole(roleName));
        }
    }
    public static async Task EnsureRolesCreated(this RoleManager<IdentityRole> roleManager)
    {
        // add all roles, that should be in database, here
        await EnsureRoleCreated(roleManager, "Developer");
    }
}

public async void Configure(..., RoleManager<IdentityRole> roleManager, ...)
{
     ...
     await roleManager.EnsureRolesCreated();
     ...
}

Now, the rules can be assigned to user

await _userManager.AddToRoleAsync(await _userManager.FindByIdAsync(User.GetUserId()), "Developer");

Or used in Authorize attribute

[Authorize(Roles = "Developer")]
public class DeveloperController : Controller
{
}
nothrow
  • 15,882
  • 9
  • 57
  • 104
  • `services.AddIdentity().AddRoleManager()` I wasn't able to add it to `services` directly. – Alex C Dec 20 '15 at 20:27
  • 2
    @AlexC, Sorry, my bad. I tried to keep it as simple as possible and removed the AddIdentity. Fixed. – nothrow Dec 20 '15 at 22:31
  • 1
    So, I've added that code to a standalone project https://github.com/AlexChesser/AspnetIdentitySample/commit/728520e7126d4ada5981e9d5807b456e86335e4e and the AspnetRoles do successfully get created, but for some reason, the pages become 'whitescreens' (I assume a 500 error, but no stacktrace) have you been able to render pages with this installed? – Alex C Dec 21 '15 at 20:15
  • ok - this commit fixes the whitescreen error https://github.com/AlexChesser/AspnetIdentitySample/commit/79831b5ca76cf280746d52b2b69a88ea5c9b6b5d notice that within EnsureRolesCreated I've switched it to a void instead of Task. – Alex C Dec 21 '15 at 21:04
  • @AlexC, reason for that is probably some race condition (Configure has not yet finished, but the rest of application assumes so). Have you tried switching Configure to be async Task instead? I'll try that as soon as I get to computer. – nothrow Dec 22 '15 at 11:46
  • 1
    having 'EnsureRolesCreated' returning void may mean that the roles are not created before Configuration finishes – nothrow Dec 22 '15 at 11:47
  • that's true - but it should be reasonably low risk in the lifecycle of a project. Roles should only really ever be initialized and persisted once, so we're talking about a few thousand miliseconds over the lifetime of a website. In theory - until we track down the cause of the whitescreen error I think it's a tradeoff worth making. I suspect some wierdness may happen when calling async in the configure method but couldn't figure it out. Moving these calls into the Database SEED may also mitigate the issue. – Alex C Dec 22 '15 at 15:06
  • I was actually thinking it was because something wasn't resolving correctly within the task and so, perhaps the rest of the code simply wasn't resuming... which may explain why there's no stack trace but also no further rendering. – Alex C Dec 22 '15 at 15:11
  • how would handle companies? – Transformer Feb 24 '17 at 04:43
6

As an improvement on Peters code above you can use this:

   var roleManager = new RoleManager<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));

   if (!roleManager.RoleExists("Member"))
            roleManager.Create(new IdentityRole("Member"));
Dave Gordon
  • 1,815
  • 4
  • 30
  • 52
3

My application was hanging on startup when I used Peter Stulinski & Dave Gordon's code samples with EF 6.0. I changed:

var roleManager = new RoleManager<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));

to

var roleManager = new RoleManager<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>(new RoleStore<IdentityRole>(**context**));

Which makes sense when in the seed method you don't want instantiate another instance of the ApplicationDBContext. This might have been compounded by the fact that I had Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer()); in the constructor of ApplicationDbContext

user1666620
  • 4,800
  • 18
  • 27
Dane W
  • 181
  • 2
  • 6
2

Roles View Model

public class RoleViewModel
{
    public string Id { get; set; }
    [Required(AllowEmptyStrings = false)]
    [Display(Name = "RoleName")]
    public string Name { get; set; }
}

Controller method

    [HttpPost]
    public async Task<ActionResult> Create(RoleViewModel roleViewModel)
    {
       if (ModelState.IsValid)
       {
           var role = new IdentityRole(roleViewModel.Name);
           var roleresult = await RoleManager.CreateAsync(role);
           if (!roleresult.Succeeded)
           {
               ModelState.AddModelError("", roleresult.Errors.First());
               return View();
           }
           return RedirectToAction("some_action");
       }
       return View();
    }
Moji
  • 5,720
  • 2
  • 38
  • 39
1

I wanted to share another solution for adding roles:

<h2>Create Role</h2>

@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<span class="label label-primary">Role name:</span>
<p>
    @Html.TextBox("RoleName", null, new { @class = "form-control input-lg" })
</p>
<input type="submit" value="Save" class="btn btn-primary" />
}

Controller:

    [HttpGet]
    public ActionResult AdminView()
    {
        return View();
    }

    [HttpPost]
    public ActionResult AdminView(FormCollection collection)
    {
        var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));

        if (roleManager.RoleExists(collection["RoleName"]) == false)
        {
            Guid guid = Guid.NewGuid();
            roleManager.Create(new IdentityRole() { Id = guid.ToString(), Name = collection["RoleName"] });
        }
        return View();
    }
JoshYates1980
  • 3,476
  • 2
  • 36
  • 57
1

If you are using the default template that is created when you select a new ASP.net Web application and selected Individual User accounts as Authentication and trying to create users with Roles so here is the solution. In the Account Controller's Register method which is called using [HttpPost], add the following lines in if condition.

using Microsoft.AspNet.Identity.EntityFramework;

var user = new ApplicationUser { UserName = model.Email, Email = model.Email };

var result = await UserManager.CreateAsync(user, model.Password);

if (result.Succeeded)
{
  var roleStore = new RoleStore<IdentityRole>(new ApplicationDbContext());
  var roleManager = new RoleManager<IdentityRole>(roleStore);
  if(!await roleManager.RoleExistsAsync("YourRoleName"))
     await roleManager.CreateAsync(new IdentityRole("YourRoleName"));

  await UserManager.AddToRoleAsync(user.Id, "YourRoleName");
  await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
  return RedirectToAction("Index", "Home");
}

This will create first create a role in your database and then add the newly created user to this role.

Hamza Khanzada
  • 1,439
  • 1
  • 22
  • 39
0
    public static void createUserRole(string roleName)
    {
        if (!System.Web.Security.Roles.RoleExists(roleName))
        {
            System.Web.Security.Roles.CreateRole(roleName);
        }
    }
Stephan Ahlf
  • 3,310
  • 5
  • 39
  • 68
0

the method i Use for creating roles is below, assigning them to users in code is also listed. the below code does be in "configuration.cs" in the migrations folder.

string [] roleNames = { "role1", "role2", "role3" };
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

                IdentityResult roleResult;
                foreach(var roleName in roleNames)
                {
                    if(!RoleManager.RoleExists(roleName))
                    {
                        roleResult = RoleManager.Create(new IdentityRole(roleName));
                    }
                }
                var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
                UserManager.AddToRole("user", "role1");
                UserManager.AddToRole("user", "role2");
                context.SaveChanges();
Kevin
  • 2,258
  • 1
  • 32
  • 40