Creación de roles en Asp.net Identity MVC 5

85

Hay muy poca documentación sobre el uso del nuevo Marco de seguridad de identidad de Asp.net.

He reunido todo lo que pude para intentar crear un nuevo rol y agregarle un usuario. Intenté lo siguiente: Agregar rol en ASP.NET Identity

que parece haber obtenido la información de este blog: crear una aplicación simple de tareas pendientes con la identidad de asp.net y asociar a los usuarios con tareas pendientes

He agregado el código a un inicializador de base de datos que se ejecuta cada vez que cambia el modelo. Falla en la RoleExistsfunción con el siguiente error:

System.InvalidOperationException ocurrió en mscorlib.dll El tipo de entidad IdentityRole no es parte del modelo para el contexto actual.

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));
    }
}

Se agradece cualquier ayuda.

colbyJax
fuente

Respuestas:

26

Verifique que tenga la siguiente firma de su MyContextclase

public class MyContext : IdentityDbContext<MyUser>

O

public class MyContext : IdentityDbContext

¡El código funciona para mí, sin ninguna modificación!

jd4u
fuente
4
Gracias a todos por sus respuestas. Todo está funcionando ahora. Verificar el contexto me llevó en la dirección correcta. Cuando se crea la identidad de asp.net, crea un nuevo contexto (ApplicationDbContext) que extiende IdentityDbContext. En mi código, estaba haciendo referencia a mi contexto original que no extendía IdentityDbContext. Si alguien más tiene este problema, verifique sus contextos y vuelva a verificar su directorio APP_DATA para asegurarse de que no está creando accidentalmente dos bases de datos.
colbyJax
74

Aquí vamos:

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
fuente
2
Esto me ayudó, especialmente porque no estaba usando Migraciones. Estoy usando DropCreateDatabaseAlways.
J86
Mi problema fue que estaba usando el contexto incorrecto. Había creado dos cadenas de conexión, una llamada IdentityDbContexty otra que estaba usando un contexto personalizado, así que cuando usé tu sugerencia AppilcationDbContext(), funcionó.
megamaiku
var roleManager = new RoleManager <IdentityRole> (nuevo RoleStore <IdentityRole> (db));
Nour Lababidi
25

Aquí está el artículo completo que describe cómo crear roles, modificar roles, eliminar roles y administrar roles usando ASP.NET Identity. También contiene la interfaz de usuario, los métodos del controlador, etc.

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

Espero que esto ayude

Gracias

Sheo Narayan
fuente
1
Su blog es bueno, pero desactualizado, ¿puede actualizar el controlador de cuenta
Aggie
Ya es para ASP.NET MVC 5 (¿Qué actualización está buscando?). Puede descargar el código fuente del enlace de GitHub especificado en el artículo.
Sheo Narayan
1
Algunas de esas funciones parecen obsoletas desde la versión 2.2.0 en la última versión. 1) ¿Puedo usar el mismo código en la versión actual? 2) ¿Cómo puedo cambiar la clave principal de Guid al correo electrónico? 3) Se agradecería cualquier recomendación sobre cómo integrar recpatcha con Identity j.mp/1nohaHe
aggie
15

En ASP.NET 5 rc1-final , hice lo siguiente:

Creado ApplicationRoleManager(de manera similar a como lo ApplicationUsercrea la plantilla)

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)
    {
    }
}

Para ConfigureServicesadentro Startup.cs, lo agregué como RoleManager

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

Para crear nuevos roles, llame desde lo Configuresiguiente:

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();
     ...
}

Ahora, las reglas se pueden asignar al usuario

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

O usado en Authorizeatributo

[Authorize(Roles = "Developer")]
public class DeveloperController : Controller
{
}
nothrow
fuente
services.AddIdentity<UserAuth, IdentityRole>().AddRoleManager<ApplicationRoleManager>() No pude agregarlo servicesdirectamente.
Alex C
2
@AlexC, lo siento, mi mal. Traté de mantenerlo lo más simple posible y eliminé AddIdentity. Fijo.
nothrow
1
Entonces, agregué ese código a un proyecto independiente github.com/AlexChesser/AspnetIdentitySample/commit/… y los AspnetRoles se crean con éxito, pero por alguna razón, las páginas se convierten en 'pantallas en blanco' (asumo un error 500, pero no stacktrace) ¿ha podido renderizar páginas con esto instalado?
Alex C
ok - esta confirmación corrige el error de pantalla blanca github.com/AlexChesser/AspnetIdentitySample/commit/… observe que dentro de EnsureRolesCreated lo cambié a vacío en lugar de Task.
Alex C
1
tener el valor de "Asegúrese de crear funciones creado" puede significar que los roles no se crean antes de que finalice la configuración
nothrow el
6

Como mejora en el código de Peters anterior, puede usar esto:

   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
fuente
3

Mi aplicación estaba suspendida en el inicio cuando usé los ejemplos de código de Peter Stulinski y Dave Gordon con EF 6.0. Cambié:

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

a

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

Lo cual tiene sentido cuando en el método de inicialización no desea crear una instancia de otra instancia de ApplicationDBContext. Esto podría haber sido agravado por el hecho de que tenía Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());en el constructor deApplicationDbContext

Dane W
fuente
2

Modelo de vista de roles

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

Método de controlador

    [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
fuente
1

Quería compartir otra solución para agregar 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" />
}

Controlador:

    [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
fuente
1

Si está utilizando la plantilla predeterminada que se crea cuando selecciona una nueva aplicación web ASP.net y selecciona Cuentas de usuario individual como Autenticación e intenta crear usuarios con roles, aquí está la solución. En el método de registro del controlador de cuenta que se llama usando [HttpPost], agregue las siguientes líneas en if condition.

utilizando 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");
}

Esto creará primero una función en su base de datos y luego agregará el usuario recién creado a esta función.

Hamza Khanzada
fuente
0
    public static void createUserRole(string roleName)
    {
        if (!System.Web.Security.Roles.RoleExists(roleName))
        {
            System.Web.Security.Roles.CreateRole(roleName);
        }
    }
Stephan Ahlf
fuente
0

el método que uso para crear roles se encuentra a continuación, y también se enumera la asignación a usuarios en el código. el siguiente código está en "configuration.cs" en la carpeta de migraciones.

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
fuente