Criação de funções na identidade Asp.net MVC 5

85

Há muito pouca documentação sobre o uso do novo Asp.net Identity Security Framework.

Reuni o que pude para tentar criar uma nova função e adicionar um usuário a ela. Tentei o seguinte: Adicionar função na identidade do ASP.NET

que parece que pode ter obtido as informações deste blog: construir um aplicativo de tarefas simples com identidade asp.net e associar usuários a tarefas

Eu adicionei o código a um Inicializador de banco de dados que é executado sempre que o modelo muda. Ele falha na RoleExistsfunção com o seguinte erro:

System.InvalidOperationException ocorreu em mscorlib.dll O tipo de entidade IdentityRole não faz parte do modelo para o contexto atual.

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

Qualquer ajuda é apreciada.

colbyJax
fonte

Respostas:

26

Verifique se você tem a seguinte assinatura de sua MyContextclasse

public class MyContext : IdentityDbContext<MyUser>

Ou

public class MyContext : IdentityDbContext

O código está funcionando para mim, sem nenhuma modificação !!!

jd4u
fonte
4
Obrigado a todos por suas respostas. Tudo está funcionando agora. Verificar o contexto me levou na direção certa. Quando a identidade asp.net é criada, ele cria um novo contexto (ApplicationDbContext) que estende IdentityDbContext. No meu código, estava fazendo referência ao meu contexto original, que não estendia IdentityDbContext. Se outra pessoa tiver esse problema, verifique seus contextos e verifique novamente o diretório APP_DATA para ter certeza de que não está criando dois bancos de dados acidentalmente.
colbyJax
74

Aqui vamos nós:

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
fonte
2
Isso me ajudou, especialmente porque eu não estava usando o Migrations. Estou usando DropCreateDatabaseAlways.
J86 de
Meu problema era que eu estava usando o contexto errado. Eu criei duas strings de conexão, uma chamada IdentityDbContexte outra que estava usando um contexto personalizado, então, quando usei sua sugestão AppilcationDbContext(), funcionou.
megamaiku
var roleManager = novo RoleManager <IdentityRole> (novo RoleStore <IdentityRole> (db));
Nour Lababidi
25

Aqui está o artigo completo que descreve como criar funções, modificar funções, excluir funções e gerenciar funções usando a identidade ASP.NET. Isso também contém interface de usuário, métodos de controlador, etc.

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

Espero que esta ajuda

obrigado

Sheo Narayan
fonte
1
Seu blog é bom, mas desatualizado, você pode atualizar o controlador de conta
aggie
Já é para ASP.NET MVC 5 (qual atualização você está procurando aggie?). Você pode baixar o código-fonte do link GitHub especificado no artigo.
Sheo Narayan
1
Algumas dessas funções parecem obsoletas a partir da versão 2.2.0. 1) posso usar o mesmo código na versão atual 2) como posso alterar a chave primária de Guid para e-mail 3) quaisquer recomendações sobre como integrar recpatcha com identidade seriam apreciadas j.mp/1nohaHe
aggie
15

Em ASP.NET 5 rc1-final, eu fiz o seguinte:

Criado ApplicationRoleManager(da mesma forma que é ApplicationUsercriado pelo modelo)

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 ConfigureServicesin Startup.cs, eu o adicionei como RoleManager

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

Para criar novas funções, ligue a partir de Configure:

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

Agora, as regras podem ser atribuídas ao usuário

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

Ou usado em Authorizeatributo

[Authorize(Roles = "Developer")]
public class DeveloperController : Controller
{
}
nothrow
fonte
services.AddIdentity<UserAuth, IdentityRole>().AddRoleManager<ApplicationRoleManager>() Não consegui adicionar servicesdiretamente.
Alex C
2
@AlexC, Desculpe, que pena. Tentei mantê-lo o mais simples possível e removi o AddIdentity. Fixo.
nothrow de
1
Então, eu adicionei esse código a um projeto autônomo github.com/AlexChesser/AspnetIdentitySample/commit/… e as AspnetRoles são criadas com sucesso, mas por algum motivo, as páginas se tornam 'telas brancas' (presumo um erro 500, mas sem stacktrace) você conseguiu renderizar páginas com este instalado?
Alex C
ok - este commit corrige o erro de tela em branco github.com/AlexChesser/AspnetIdentitySample/commit/ ... observe que dentro de EnsureRolesCreated eu mudei para void em vez de Task.
Alex C
1
ter 'GuaranteeRolesCreated' retornando void pode significar que as funções não são criadas antes que a configuração termine
nothrow
6

Como uma melhoria no código Peters acima, você pode usar isto:

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

Meu aplicativo estava travando na inicialização quando usei os exemplos de código de Peter Stulinski e Dave Gordon com EF 6.0. Eu mudei:

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

para

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

O que faz sentido quando no método seed você não deseja instanciar outra instância do ApplicationDBContext. Isso pode ter sido agravado pelo fato de que eu tinha Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());no construtor deApplicationDbContext

Dane W
fonte
2

Modelo de visualização de funções

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

Método de controle

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

Eu queria compartilhar outra solução para adicionar funções:

<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
fonte
1

Se você estiver usando o modelo padrão criado quando você seleciona um novo aplicativo da Web ASP.net e seleciona Contas de usuário individual como Autenticação e tenta criar usuários com funções, aqui está a solução. No método de registro do controlador de conta que é chamado usando [HttpPost], adicione as seguintes linhas em if condition.

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

Isso criará, primeiro, criará uma função em seu banco de dados e, em seguida, adicionará o usuário recém-criado a esta função.

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

o método que eu uso para criar funções está abaixo, atribuindo-as a usuários no código também está listado. o código abaixo está em "configuration.cs" na pasta de migrações.

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
fonte