List all Roles in CheckBox and mark the roles that the User has

7

I am creating a User Management System in Asp.net MVC 4 with two Simple Tables.

Users and Roles.

I can create the users normally by selecting the Roles that they will have.

At Edit time I'm trying to list all the Roles in CheckBox and check Only the roles that the user has, so that you can change the user's roles in the edit.

Here's how I'm trying to do it.

Controller

public ActionResult Edit(int id = 0)
{
    var usuario = _ctx.Usuarios.Include("Roles").ToList();
    var user = usuario.SingleOrDefault(u => u.UsuarioId == id);

    if (user == null)
    {
        return HttpNotFound();
    }

    ViewBag.Praca = new SelectList(_ctx.Pracas.ToList(), "PracaId", "Nome");
    ViewBag.Roles = _p.GetAllRoles();

    return View(user);
}

View Edit

<div class="col-lg-7">
    <h4>Permissões</h4>

    @foreach (var item in ViewBag.Roles)
    {
        foreach (var roles in Model.Roles)
        {
           <label style="display: block">
                <input type="checkbox" checked="@item.Equals(roles.Nome)" /> @item
           </label>
        }
     }
</div>

In this way the data is coming duplicates.

Ex: Let's say there are two Roles "Admin" and "Manager" and the User has the Two, the output is:

[x] Admin
[ ] Admin
[ ] Gerente
[x] Gerente

If the User has only one of the Outgoing Roles, it goes out the way I want it to be.

[x] Admin
[ ] Gerente
    
asked by anonymous 19.02.2014 / 16:25

4 answers

3

First, your logic is not very good, since you are using two% nested%, printing things on the page ... this would be the logic of a table, but not a list.

The correct logic for a list is to print the foreach within the first input , which is what iterates over all input options that may be ... from what I understand foreach contains all the options of roles.

In addition, putting ViewBag.Roles or checked="true" in your HTML will do the same ... both checkboxes will be selected. To not select, the checked="false" attribute must be removed in its entirety.

Do this as it should:

<div class="col-lg-7">
    <h4>Permissões</h4>

    @foreach (var role in ViewBag.Roles)
    {
        bool estaSelecionado = false;
        foreach (var roleUsuario in Model.Roles)
        {
            if (roleUsuario.Nome == role)
            {
                estaSelecionado = true;
                break;
            }
        }

        <label style="display: block">
            @if (estaSelecionado)
            {
                <input type="checkbox" checked="checked" /> @role
            }
            else
            {
                <input type="checkbox" /> @role
            }
        </label>
     }
</div>

Now for simplicity, you can use LINQ to objects and write everything in a few lines.

EDIT

Since simplicity is being questioned you can use the code below, which is simpler, uses LINQ, and has semantically correct markup.

<div class="col-lg-7">
    <h4>Permissões</h4>

    @foreach (var role in ViewBag.Roles)
    {
        var roleId = "role-" + role.Replace(" ", "-");
        <div>
            @Html.CheckBox("role",
                    Model.Roles.Any(r => r.Nome == role),
                    new { value = role, id = roleId })
            <label for="@roleId">@role</label>
        </div>
     }
</div>

I'd like to point out that the checked tag is being used wrongly in your code, the label ... attribute is missing in the way I mentioned in the previous example.

I also noticed that you did not post your POST action to get the data after editing ... so I put all the checkboxes with the same name, so you could do an action like this:

[HttpPost]
public ActionResult Edit(int id = 0, string[] role)
{
    // role contém uma lista dos roles selecionados, mas não contém os não selecionados
}
    
19.02.2014 / 17:11
3

Just complementing the answers: In MVC4 there are two classes and one attribute that implement authentication, user system and roles. These are:

  • MembershipProvider
  • RoleProvider
  • AuthorizeAttribute

Just derive each one and write the override s. With this you can use the native methods of the Framework, for example:

  • User.IsInRole("MinhaRole") ;
  • Roles.CreateRole("MinhaRole") ;

Or decorate your Actions with the [Authorize] attribute.

You can create registration screens and base your implementations on other models.

Examples:

Root Web.config

<system.web>
    <roleManager enabled="true" defaultProvider="MyRoleProvider">
      <providers>
        <clear />
        <add name="MyRoleProvider" type="TesteMaroto.Infrastructure.MyRoleProvider" connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </roleManager>
    <membership defaultProvider="MyMembershipProvider">
      <providers>
        <clear />
        <add name="MyMembershipProvider" type="TesteMaroto.Infrastructure.MyMembershipProvider" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
      </providers>
    </membership>
    <machineKey validationKey="2183859A758E675951A39436AFD2FE57ABF398DA3627AE39B76075C995CF0094488F816CA5E6DA572627612C14F934589FF5B0CA92CC55F51F9099B10EB3F6F1" decryptionKey="8A46124FEC091DE2C82EDF529F884CC24CC8F38D6839A9FA6F86279DE5654261" validation="SHA1" decryption="AES" />
  </system.web>
  

Attention : Generate your <machineKey> here: link

MembershipProvider

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace TesteMaroto.Infrastructure
{
    public class MyMembershipProvider : MembershipProvider
    {
        public override string ApplicationName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// Implemente aqui seu procedimento de alteração de senha.
        /// </summary>
        /// <param name="username">Login do Usuário</param>
        /// <param name="oldPassword">Senha antiga</param>
        /// <param name="newPassword">Nova senha</param>
        /// <returns>True se a operação foi feita com sucesso; False em caso contrário.</returns>
        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método se você quiser criar um esquema de recuperação de senha por pergunta e resposta.
        /// Este método altera a pergunta e a resposta.
        /// </summary>
        /// <param name="username">Login do Usuário</param>
        /// <param name="password">Senha</param>
        /// <param name="newPasswordQuestion">Nova pergunta para recuperação da senha</param>
        /// <param name="newPasswordAnswer">Nova resposta para recuperação da senha</param>
        /// <returns>True se a operação foi feita com sucesso; False em caso contrário.</returns>
        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método um usuário e retorna um objeto do tipo MembershipUser preenchido.
        /// </summary>
        /// <param name="username">Login do Usuário</param>
        /// <param name="password">Senha</param>
        /// <param name="email">E-Mail</param>
        /// <param name="passwordQuestion">Pergunta para recuperação de senha</param>
        /// <param name="passwordAnswer">Resposta para recuperação de senha</param>
        /// <param name="isApproved">É aprovado ou precisa de uma confirmação extra, como aquelas enviadas por e-mail</param>
        /// <param name="providerUserKey">O objeto que representa a chave primária do seu model de usuário. Pode ser int, Guid...</param>
        /// <param name="status">Um objeto do Status da Criação. É preenchido dentro deste método</param>
        /// <returns>Objeto do tipo MembershipUser</returns>
        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para excluir um usuário.
        /// </summary>
        /// <param name="username">Nome do usuário</param>
        /// <param name="deleteAllRelatedData">Indicativo para exclusão de todos os dados relacionados ao usuário.</param>
        /// <returns>True se a operação foi feita com sucesso; False em caso contrário.</returns>
        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework se você permite reiniciar a senha do usuário ou não.
        /// </summary>
        public override bool EnablePasswordReset
        {
            get { 
                // return true; ou então return false;
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework se você permite que a senha seja reenviada ao usuário caso ele assim solicite.
        /// </summary>
        public override bool EnablePasswordRetrieval
        {
            get {
                // return true; ou então return false;
                throw new NotImplementedException(); 
            }
        }

        /// <summary>
        /// Implemente este método para o Framework poder retornar todos os usuários cadastrados por um determinado e-mail.
        /// MembershipUserCollection é uma lista especial.
        /// </summary>
        /// <param name="emailToMatch">Endereço de e-mail a ser localizado</param>
        /// <param name="pageIndex">Índice da página. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <param name="pageSize">Número de registros para uma página. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <param name="totalRecords">Total de registros encontrados. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <returns>Objeto do tipo MembershipUserCollection</returns>
        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework poder retornar todos os usuários cadastrados por um determinado nome.
        /// MembershipUserCollection é uma lista especial.
        /// </summary>
        /// <param name="usernameToMatch">Nome a ser localizado</param>
        /// <param name="pageIndex">Índice da página. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <param name="pageSize">Número de registros para uma página. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <param name="totalRecords">Total de registros encontrados. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <returns>Objeto do tipo MembershipUserCollection</returns>
        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework poder obter todos os usuários.
        /// </summary>
        /// <param name="pageIndex">Índice da página. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <param name="pageSize">Número de registros para uma página. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <param name="totalRecords">Total de registros encontrados. Serve para fazer paginação pra uma View, por exemplo</param>
        /// <returns>Objeto do tipo MembershipUserCollection</returns>
        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework poder retornar o número de usuários online.
        /// </summary>
        /// <returns>Número de usuários online.</returns>
        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework poder retornar a senha de um usuário baseado na resposta fornecida em tela.
        /// </summary>
        /// <param name="username">Login do usuário</param>
        /// <param name="answer">Resposta fornecida</param>
        /// <returns>Senha, se a resposta estiver correta.</returns>
        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework poder retornar todos os dados sobre um usuário procurando pelo Login do usuário.
        /// </summary>
        /// <param name="username">Login do usuário</param>
        /// <param name="userIsOnline">Indicativo de usuário online</param>
        /// <returns>Objeto do tipo MembershipUser</returns>
        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Implemente este método para o Framework poder retornar todos os dados sobre um usuário procurando pela chave primária do Model.
        /// </summary>
        /// <param name="providerUserKey">A chave do Model (pode ser int, Guid...)</param>
        /// <param name="userIsOnline">Indicativo de usuário online</param>
        /// <returns>Objeto do tipo MembershipUser</returns>
        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework poder retornar o Login de um usuário procurando pelo e-mail do usuário.
        /// </summary>
        /// <param name="email">E-mail do usuário</param>
        /// <returns>Login do Usuário</returns>
        public override string GetUserNameByEmail(string email)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework quantas tentativas erradas de senha tem um usuário antes da sua conta ser bloqueada.
        /// </summary>
        public override int MaxInvalidPasswordAttempts
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework quantos caracteres não-alfanuméricos deve ter a senha do usuário.
        /// </summary>
        public override int MinRequiredNonAlphanumericCharacters
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework a quantidade mínima de caracteres que deve ter a senha do usuário.
        /// </summary>
        public override int MinRequiredPasswordLength
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework o tempo da janela de tentativas de senha do usuário (em minutos).
        /// </summary>
        public override int PasswordAttemptWindow
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework o formato da senha do usuário.
        /// </summary>
        public override MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework a expressão regular que avalia a força da senha do usuário.
        /// </summary>
        public override string PasswordStrengthRegularExpression
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework se o registro do usuário requer pergunta e resposta para recuperação de senha.
        /// </summary>
        public override bool RequiresQuestionAndAnswer
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework se o e-mail deve ser único no registro de usuário.
        /// </summary>
        public override bool RequiresUniqueEmail
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Implemente este método para indicar ao Framework como reiniciar e recuperar uma senha gerada pelo sistema para um usuário.
        /// </summary>
        /// <param name="username">Login do usuário</param>
        /// <param name="answer">Resposta de senha.</param>
        /// <returns>Nova senha gerada, se a resposta estiver correta.</returns>
        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework como desbloquear um usuário bloqueado no sistema.
        /// </summary>
        /// <param name="userName">Login do usuário</param>
        /// <returns>True se a operação foi feita com sucesso; False em caso contrário.</returns>
        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework como atualizar os dados de um usuário.
        /// </summary>
        /// <param name="user">Dados do usuário a ser atualizado.</param>
        public override void UpdateUser(MembershipUser user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente esta property para indicar ao Framework como validar um usuário para login.
        /// </summary>
        /// <param name="username">Login do usuário</param>
        /// <param name="password">Senha do usuário</param>
        /// <returns>True se usuário acertou a senha e pode se considerar autenticado; False em caso contrário.</returns>
        public override bool ValidateUser(string username, string password)
        {
            throw new NotImplementedException();
        }
    }
}

RoleProvider

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace TesteMaroto.Infrastructure
{
    public class MyRoleProvider : RoleProvider
    {
        /// <summary>
        /// Implemente este método para o Framework adicionar usuários a roles.
        /// </summary>
        /// <param name="usernames">Array de Logins.</param>
        /// <param name="roleNames">Roles às quais os usuários serão associados.</param>
        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        public override string ApplicationName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// Implemente este método para o Framework criar uma Role.
        /// </summary>
        /// <param name="roleName">Nome da Role.</param>
        public override void CreateRole(string roleName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework excluir uma Role.
        /// </summary>
        /// <param name="roleName">Nome da Role</param>
        /// <param name="throwOnPopulatedRole">Indicativo se deve haver uma exceção caso a exclusão seja de uma Role que tem usuários associados a ela</param>
        /// <returns>True se a operação foi feita com sucesso; False em caso contrário.</returns>
        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework procurar se um usuário está associado a uma Role.
        /// </summary>
        /// <param name="roleName">Nome da Role</param>
        /// <param name="usernameToMatch">Usuário para pesquisa</param>
        /// <returns>Lista de usuários encontrados</returns>
        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework retornar todas as Roles existentes.
        /// </summary>
        /// <returns>Array de Strings com o nome das Roles.</returns>
        public override string[] GetAllRoles()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework retornar todas as Roles de um usuário.
        /// </summary>
        /// <param name="username">Login do usuário</param>
        /// <returns>Array de Strings com o nome das roles.</returns>
        public override string[] GetRolesForUser(string username)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework retornar todos os usuários de uma Role.
        /// </summary>
        /// <param name="roleName">Nome da Role</param>
        /// <returns>Array de Strings com os Logins dos usuários.</returns>
        public override string[] GetUsersInRole(string roleName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework verificar se um usuário está em uma Role.
        /// </summary>
        /// <param name="username">Login do usuário</param>
        /// <param name="roleName">Nome da role</param>
        /// <returns>True se usuário está numa Role; False em caso contrário.</returns>
        public override bool IsUserInRole(string username, string roleName)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework remover usuários das Roles passadas como parâmetro.
        /// </summary>
        /// <param name="usernames">Logins dos usuários</param>
        /// <param name="roleNames">Nomes das Roles</param>
        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Implemente este método para o Framework verificar se uma Role existe.
        /// </summary>
        /// <param name="roleName">Nome da Role</param>
        /// <returns>True se Role existe; False em caso contrário.</returns>
        public override bool RoleExists(string roleName)
        {
            throw new NotImplementedException();
        }
    }
}
    
19.02.2014 / 19:16
1

You have the existing roles in ViewBag.Roles , correct? So your foreach should look like this:

@foreach (var role in ViewBag.Roles)
{
    <label style="display: block">
         <input type="checkbox" "@(Model.Roles.Select(n => n.Nome).Contains(role) ? "checked=checked" : "")" /> @role
    </label>
 }

Where Model.Roles.Select(n => n.Nome).Contains(role) ? "checked" : "" checks whether Model.Roles contains that iteration role and assigns checked=checked to checkbox .

    
19.02.2014 / 17:14
0

The checked property is not Boolean, once declared it selects itself.

Try using this in View:

<div class="col-lg-7">
<h4>Permissões</h4>

@foreach (var item in ViewBag.Roles)
{
    foreach (var roles in Model.Roles)
    {
       <label style="display: block">
            @if(item.Equals(roles.Nome))
            {
                 <input type="checkbox" checked /> @item
            }
            else
            {
                 <input type="checkbox"/> @item 
            }
       </label>
    }
 }

    
19.02.2014 / 16:45