Asignar roles a los usuarios (VB)

por Scott Mitchell

Nota:

Desde que se escribió este artículo, los proveedores de pertenencia a ASP.NET han sido reemplazados por ASP.NET Identity. Se recomienda encarecidamente actualizar las aplicaciones para usar la plataforma ASP.NET Identity en lugar de los proveedores de pertenencia destacados en el momento en que se escribió este artículo. ASP.NET Identity tiene una serie de ventajas sobre el sistema de pertenencia ASP.NET, incluidas las siguientes:

  • Mejor rendimiento
  • Extensibilidad y capacidad de prueba mejoradas
  • Compatibilidad con OAuth, OpenID Connect y autenticación en dos fases
  • Compatibilidad con identidades basadas en notificaciones
  • Mejor interoperabilidad con ASP.Net Core

Descargar código o Descargar PDF

En este tutorial crearemos dos páginas de ASP.NET para ayudar a administrar qué usuarios pertenecen a los roles. La primera página incluirá instalaciones para ver a qué usuarios pertenecen a un rol determinado, a qué roles pertenece un usuario determinado y a la capacidad de asignar o quitar un usuario determinado de un rol determinado. En la segunda página, aumentaremos el control CreateUserWizard para que incluya un paso para especificar a qué roles pertenece el usuario recién creado. Esto resulta útil en escenarios en los que un administrador puede crear nuevas cuentas de usuario.

Introducción

En el tutorial anterior se examinaron el marco roles y SqlRoleProvider; vimos cómo usar la Roles clase para crear, recuperar y eliminar roles. Además de crear y eliminar roles, es necesario poder asignar o quitar usuarios de un rol. Desafortunadamente, ASP.NET no se envía con ningún control web para administrar qué usuarios pertenecen a qué roles. En su lugar, debemos crear nuestras propias páginas de ASP.NET para administrar estas asociaciones. La buena noticia es que agregar y quitar usuarios a roles es bastante fácil. La Roles clase contiene varios métodos para agregar uno o varios usuarios a uno o varios roles.

En este tutorial crearemos dos páginas de ASP.NET para ayudar a administrar qué usuarios pertenecen a los roles. La primera página incluirá instalaciones para ver a qué usuarios pertenecen a un rol determinado, a qué roles pertenece un usuario determinado y a la capacidad de asignar o quitar un usuario determinado de un rol determinado. En la segunda página, aumentaremos el control CreateUserWizard para que incluya un paso para especificar a qué roles pertenece el usuario recién creado. Esto resulta útil en escenarios en los que un administrador puede crear nuevas cuentas de usuario.

Comencemos.

Enumerar qué usuarios pertenecen a los roles

El primer orden de negocio para este tutorial es crear una página web desde la que se pueden asignar roles a los usuarios. Antes de preocuparnos por cómo asignar usuarios a roles, primero nos centraremos en cómo determinar qué usuarios pertenecen a qué roles. Hay dos maneras de mostrar esta información: "por rol" o "por usuario". Podríamos permitir que el visitante seleccione un rol y, a continuación, mostrar todos los usuarios que pertenecen al rol (la pantalla "por rol"), o podríamos pedir al visitante que seleccione un usuario y, a continuación, mostrar los roles asignados a ese usuario (la pantalla "por usuario").

La vista "por rol" es útil en circunstancias en las que el visitante quiere conocer el conjunto de usuarios que pertenecen a un rol determinado; la vista "por usuario" es ideal cuando el visitante necesita conocer los roles de un usuario determinado. Vamos a hacer que nuestra página incluya interfaces "por rol" y "por usuario".

Comenzaremos con la creación de la interfaz "por usuario". Esta interfaz constará de una lista desplegable y una lista de casillas. La lista desplegable se rellenará con el conjunto de usuarios del sistema; las casillas enumerarán los roles. Al seleccionar un usuario en la lista desplegable, se comprobarán los roles a los que pertenece el usuario. La persona que visita la página puede activar o desactivar las casillas para agregar o quitar el usuario seleccionado de los roles correspondientes.

Nota:

El uso de una lista desplegable para enumerar las cuentas de usuario no es una opción ideal para sitios web donde puede haber cientos de cuentas de usuario. Una lista desplegable está diseñada para permitir que un usuario elija un elemento de una lista relativamente corta de opciones. Rápidamente se vuelve inconfundible a medida que crece el número de elementos de lista. Si va a crear un sitio web que tenga un número potencialmente elevado de cuentas de usuario, es posible que desee considerar el uso de una interfaz de usuario alternativa, como una GridView paginable o una interfaz filtrable que muestra al visitante que elija una carta y, a continuación, solo muestra a los usuarios cuyo nombre de usuario comienza con la letra seleccionada.

Paso 1: Compilar la interfaz de usuario "Por usuario"

Abra la página UsersAndRoles.aspx. En la parte superior de la página, agregue un control Web etiqueta denominado ActionStatus y borre su Text propiedad. Usaremos esta etiqueta para proporcionar comentarios sobre las acciones realizadas, mostrando mensajes como "El usuario Tito se ha agregado al rol Administradores" o "El usuario Jisun se ha quitado del rol Supervisores". Para que estos mensajes destaquen, establezca la propiedad label CssClass en "Importante".

<p align="center"> 
     <asp:Label ID="ActionStatus" runat="server" CssClass="Important"> </asp:Label> 
</p>

A continuación, agregue la siguiente definición de clase CSS a la hoja de Styles.css estilos:

.Important 
{ 
     font-size: large; 
     color: Red; 
}

Esta definición de CSS indica al explorador que muestre la etiqueta mediante una fuente grande y roja. En la figura 1 se muestra este efecto a través del Diseñador de Visual Studio.

The Label's CssClass Property Results in a Large, Red Font

Figura 1: La propiedad de la CssClass etiqueta da como resultado una fuente grande y roja (haga clic para ver la imagende tamaño completo)

A continuación, agregue un DropDownList a la página, establezca su ID propiedad UserListen y establezca su AutoPostBack propiedad en True. Usaremos este DropDownList para enumerar todos los usuarios del sistema. Este DropDownList se enlazará a una colección de objetos MembershipUser. Dado que queremos que DropDownList muestre la propiedad UserName del objeto MembershipUser (y úsela como valor de los elementos de lista), establezca las propiedades DataTextField y DataValueField DropDownList en "UserName".

Debajo de DropDownList, agregue un repetidor denominado UsersRoleList. Este repetidor enumerará todos los roles del sistema como una serie de casillas. Defina el ItemTemplate del repetidor con el marcado declarativo siguiente:

<asp:Repeater ID="UsersRoleList" runat="server"> 
     <ItemTemplate> 
          <asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true" 
               Text='<%# Container.DataItem %>' /> 
          <br /> 
     </ItemTemplate> 
</asp:Repeater>

El ItemTemplate marcado incluye un único control web CheckBox denominado RoleCheckBox. La propiedad de AutoPostBack CheckBox se establece en True y la Text propiedad está enlazada a Container.DataItem. La razón por la que la sintaxis de enlace de datos es simplemente Container.DataItem porque el marco roles devuelve la lista de nombres de rol como una matriz de cadenas y es esta matriz de cadenas que se enlazará al repetidor. Una descripción exhaustiva de por qué se usa esta sintaxis para mostrar el contenido de una matriz enlazada a un control web de datos está fuera del ámbito de este tutorial. Para obtener más información sobre este asunto, consulte Enlace de una matriz escalar a un control web de datos.

Llegados a este punto, el marcado declarativo de su interfaz "por usuario" debería tener un aspecto similar al siguiente:

<h3>Manage Roles By User</h3> 
<p> 
     <b>Select a User:</b> 
     <asp:DropDownList ID="UserList" runat="server" AutoPostBack="True" 
          DataTextField="UserName" DataValueField="UserName"> 
     </asp:DropDownList> 
</p> 
<p> 
     <asp:Repeater ID="UsersRoleList" runat="server"> 
          <ItemTemplate> 
               <asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true" 
                    Text='<%# Container.DataItem %>' /> 
               <br /> 
          </ItemTemplate> 
     </asp:Repeater> 
</p>

Ahora estamos listos para escribir el código para enlazar el conjunto de cuentas de usuario a DropDownList y el conjunto de roles en el repetidor. En la clase de código subyacente de la página, agregue un método denominado BindUsersToUserList y otro denominado BindRolesList, con el código siguiente:

Private Sub BindUsersToUserList() 
     ' Get all of the user accounts 
     Dim users As MembershipUserCollection = Membership.GetAllUsers() 
     UserList.DataSource = users 
     UserList.DataBind() 
End Sub 
 
Private Sub BindRolesToList() 
     ' Get all of the roles 
     Dim roleNames() As String = Roles.GetAllRoles() 
     UsersRoleList.DataSource = roleNames 
     UsersRoleList.DataBind() 
End Sub

El BindUsersToUserList método recupera todas las cuentas de usuario del sistema a través del Membership.GetAllUsers método. Esto devuelve un MembershipUserCollection objeto, que es una colección de MembershipUser instancias. A continuación, esta colección se enlaza a UserList DropDownList. Las MembershipUser instancias que maquillan la colección contienen una variedad de propiedades, como UserName, Email, CreationDate y IsOnline. Para indicar a DropDownList que muestre el valor de la UserName propiedad, asegúrese de que las UserList propiedades y DataValueField DropDownList DataTextField se han establecido en "UserName".

Nota:

El método Membership.GetAllUsers tiene dos sobrecargas: una que no acepta parámetros de entrada y devuelve todos los usuarios y uno que toma valores enteros para el índice de página y el tamaño de página, y devuelve solo el subconjunto especificado de los usuarios. Cuando hay grandes cantidades de cuentas de usuario que se muestran en un elemento de interfaz de usuario paginable, la segunda sobrecarga se puede usar para paginar de forma más eficaz a través de los usuarios, ya que devuelve solo el subconjunto preciso de cuentas de usuario en lugar de todas ellas.

El método BindRolesToList comienza llamando al Rolesmétodo de la clase GetAllRoles, que devuelve una matriz de cadenas que contiene los roles del sistema. A continuación, esta matriz de cadenas se enlaza al repetidor.

Por último, es necesario llamar a estos dos métodos cuando la página se carga por primera vez. Agregue el código siguiente al controlador de eventos Page_Load :

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     If Not Page.IsPostBack Then 
          ' Bind the users and roles 
          BindUsersToUserList() 
          BindRolesToList() 
     End If 
End Sub

Con este código en vigor, dedique un momento a visitar la página a través de un explorador; la pantalla debe ser similar a la figura 2. Todas las cuentas de usuario se rellenan en la lista desplegable y, debajo, cada rol aparece como una casilla. Dado que establecemos las AutoPostBack propiedades de DropDownList y CheckBoxes en True, el cambio del usuario seleccionado o la comprobación o desactivación de un rol provoca una devolución de entrada. Sin embargo, no se realiza ninguna acción porque todavía tenemos que escribir código para controlar estas acciones. Abordaremos estas tareas en las dos secciones siguientes.

The Page Displays the Users and Roles

Figura 2: La página Muestra los usuarios y roles (haga clic para ver la imagen de tamaño completo)

Comprobación de los roles a los que pertenece el usuario seleccionado

Cuando la página se carga por primera vez, o cada vez que el visitante selecciona un nuevo usuario de la lista desplegable, es necesario actualizar las UsersRoleListcasillas de verificación para que una casilla de rol determinada solo esté activada si el usuario seleccionado pertenece a ese rol. Para ello, cree un método denominado CheckRolesForSelectedUser con el código siguiente:

Private Sub CheckRolesForSelectedUser() 
     ' Determine what roles the selected user belongs to 
     Dim selectedUserName As String = UserList.SelectedValue 
     Dim selectedUsersRoles() As String = Roles.GetRolesForUser(selectedUserName) 
 
     ' Loop through the Repeater's Items and check or uncheck the checkbox as needed 
     For Each ri As RepeaterItem In UsersRoleList.Items 
          ' Programmatically reference the CheckBox 
          Dim RoleCheckBox As CheckBox = CType(ri.FindControl("RoleCheckBox"), CheckBox) 
          ' See if RoleCheckBox.Text is in selectedUsersRoles 
          If Linq.Enumerable.Contains(Of String)(selectedUsersRoles, RoleCheckBox.Text) Then 
               RoleCheckBox.Checked = True 
          Else 
               RoleCheckBox.Checked = False 
          End If 
     Next 
End Sub

El código anterior comienza por determinar quién es el usuario seleccionado. A continuación, usa el método GetRolesForUser(userName) de la clase Roles para devolver el conjunto de roles del usuario especificado como una matriz de cadenas. A continuación, se enumeran los elementos del repetidor y se hace referencia mediante programación a CheckBox de RoleCheckBox cada elemento. CheckBox solo se comprueba si el rol al que corresponde se encuentra dentro de la selectedUsersRoles matriz de cadenas.

Nota:

La Linq.Enumerable.Contains(Of String)(...) sintaxis no se compilará si usa ASP.NET versión 2.0. El Contains(Of String) método forma parte de la biblioteca LINQ, que es nueva en ASP.NET 3.5. Si sigue usando ASP.NET versión 2.0, use el Array.IndexOf(Of String) método en su lugar.

El CheckRolesForSelectedUser método debe llamarse en dos casos: cuando la página se carga por primera vez y cada vez que se cambia el UserList índice seleccionado de DropDownList. Por lo tanto, llame a este método desde el Page_Load controlador de eventos (después de las llamadas a BindUsersToUserList y BindRolesToList). Además, cree un controlador de eventos para el evento DropDownList SelectedIndexChanged y llame a este método desde allí.

Protected Sub Page_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Load 
     If Not Page.IsPostBack Then 
          ' Bind the users and roles 
          BindUsersToUserList() 
          BindRolesToList() 
          ' Check the selected user's roles 
          CheckRolesForSelectedUser() 
     End If 
End Sub 
 
... 
 
Protected Sub UserList_SelectedIndexChanged(ByVal sender As Object,ByVal e As System.EventArgs) Handles UserList.SelectedIndexChanged 
     CheckRolesForSelectedUser() 
End Sub

Con este código en su lugar, puede probar la página a través del explorador. Sin embargo, dado que la UsersAndRoles.aspx página carece actualmente de la capacidad de asignar usuarios a roles, ningún usuario tiene roles. Vamos a crear la interfaz para asignar usuarios a roles en un momento, por lo que puede tomar mi palabra que este código funciona y comprobar que lo hace más adelante, o bien puede agregar manualmente usuarios a roles insertando registros en la aspnet_UsersInRoles tabla para probar esta funcionalidad ahora.

Asignación y eliminación de usuarios de roles

Cuando el visitante comprueba o desactiva una casilla en el repetidor UsersRoleList, es necesario agregar o quitar el usuario seleccionado del rol correspondiente. La propiedad de AutoPostBack CheckBox se establece actualmente en True, lo que hace que una devolución de entrada se active o desactive una casilla en el Repetidor. En resumen, es necesario crear un controlador de eventos para el evento de CheckChanged CheckBox. Dado que CheckBox está en un control Repeater, es necesario agregar manualmente la fontanería del controlador de eventos. Para empezar, agregue el controlador de eventos a la clase de código subyacente como método Protected, de la siguiente manera:

Protected Sub RoleCheckBox_CheckChanged(ByVal sender As Object, ByVal e As EventArgs) 
 
End Sub

Volveremos a escribir el código para este controlador de eventos en un momento. Pero primero vamos a completar la fontanería de control de eventos. En checkBox dentro de la ItemTemplatepropiedad repeater, agregue OnCheckedChanged="RoleCheckBox_CheckChanged". Esta sintaxis conectan el RoleCheckBox_CheckChanged controlador de eventos al RoleCheckBoxevento de CheckedChanged.

<asp:CheckBox runat="server" ID="RoleCheckBox" 
     AutoPostBack="true" 
     Text='<%# Container.DataItem %>' 
     OnCheckedChanged="RoleCheckBox_CheckChanged" />

Nuestra tarea final es completar el controlador de RoleCheckBox_CheckChanged eventos. Es necesario empezar haciendo referencia al control CheckBox que generó el evento porque esta instancia de CheckBox nos indica qué rol se ha comprobado o desmarcado a través de sus Text propiedades y Checked. Utilizando esta información junto con el UserName del usuario seleccionado, añadimos o eliminamos al usuario del rol a través de la Roles de la AddUserToRole de la clase o método RemoveUserFromRole.

Protected Sub RoleCheckBox_CheckChanged(ByVal sender As Object, ByVal e As EventArgs) 
     'Reference the CheckBox that raised this event 
     Dim RoleCheckBox As CheckBox = CType(sender, CheckBox) 
 
     ' Get the currently selected user and role 
     Dim selectedUserName As String = UserList.SelectedValue 
     Dim roleName As String = RoleCheckBox.Text 
 
     ' Determine if we need to add or remove the user from this role 
     If RoleCheckBox.Checked Then 
          ' Add the user to the role 
          Roles.AddUserToRole(selectedUserName, roleName) 
          ' Display a status message 
          ActionStatus.Text = String.Format("User {0} was added to role {1}.", selectedUserName,roleName) 
     Else 
          ' Remove the user from the role 
          Roles.RemoveUserFromRole(selectedUserName, roleName) 
          ' Display a status message 
          ActionStatus.Text = String.Format("User {0} was removed from role {1}.", selectedUserName,roleName) 
     End If 
End Sub

El código anterior comienza haciendo referencia mediante programación a la casilla que generó el evento, que está disponible a través del sender parámetro input. Si la casilla está activada, el usuario seleccionado se agrega al rol especificado; de lo contrario, se quitan del rol. En cualquier caso, la ActionStatus etiqueta muestra un mensaje que resume la acción que acaba de realizar.

Tómese un momento para probar esta página a través de un navegador. Seleccione el usuario Tito y, a continuación, agregue Tito a los roles Administradores y Supervisores.

Tito Has Been Added to the Administrators and Supervisors Roles

Figura 3: Se ha agregado Tito a los roles administradores y supervisores (haga clic para ver la imagende tamaño completo)

A continuación, seleccione el usuario Bruce en la lista desplegable. Hay un postback y las casillas del repetidor se actualizan a través de CheckRolesForSelectedUser. Puesto que Bruce aún no pertenece a ningún rol, las dos casillas están desactivadas. A continuación, agregue Bruce al rol Supervisores.

Bruce Has Been Added to the Supervisors Role

Figura 4: Se ha agregado Bruce al rol supervisores (haga clic para ver la imagen de tamaño completo)

Para comprobar aún más la funcionalidad del CheckRolesForSelectedUser método, seleccione un usuario distinto de Tito o Bruce. Observe cómo las casillas se desactivan automáticamente, lo que indica que no pertenecen a ningún rol. Volver al principio Las casillas Administradores y Supervisores deben estar activadas.

Paso 2: Compilar la interfaz de usuario "Por roles"

En este momento hemos completado la interfaz "by users" y estamos listos para empezar a abordar la interfaz "por roles". La interfaz "por roles" solicita al usuario que seleccione un rol en una lista desplegable y, a continuación, muestra el conjunto de usuarios que pertenecen a ese rol en GridView.

Agregue otro control DropDownList al UsersAndRoles.aspx page. Coloque este debajo del control Repeater, asígnelo RoleListel nombre y establezca su AutoPostBack propiedad en True. Debajo de eso, agregue un control GridView y asígnele el nombre RolesUserList. Esta clase GridView enumerará los usuarios que pertenecen al rol seleccionado. Establezca la propiedad de AutoGenerateColumns GridView en False, agregue un TemplateField a la colección de Columns la cuadrícula y establezca su HeaderText propiedad en "Users". Defina TemplateField ItemTemplate para que muestre el valor de la expresión Container.DataItem de enlace de datos en la Text propiedad de una etiqueta denominada UserNameLabel.

Después de agregar y configurar GridView, el marcado declarativo de la interfaz "por rol" debe ser similar al siguiente:

<h3>Manage Users By Role</h3> 
<p> 
     <b>Select a Role:</b> 
     <asp:DropDownList ID="RoleList" runat="server" AutoPostBack="true"></asp:DropDownList> 
</p> 
<p> 
     <asp:GridView ID="RolesUserList" runat="server" AutoGenerateColumns="false" 
          EmptyDataText="No users belong to this role."> 
          <Columns> 
               <asp:TemplateField HeaderText="Users"> 
                    <ItemTemplate> 
                         <asp:Label runat="server" id="UserNameLabel" 
                              Text='<%# Container.DataItem %>'></asp:Label> 
                    </ItemTemplate> 
               </asp:TemplateField> 
          </Columns> 
     </asp:GridView> 
</p>

Es necesario rellenar DropDownList RoleList con el conjunto de roles del sistema. Para ello, actualice el BindRolesToList método para que se enlace la matriz de cadenas devuelta por el Roles.GetAllRoles método a RolesList DropDownList (así como el repetidor UsersRoleList).

Private Sub BindRolesToList() 
     ' Get all of the roles 
     Dim roleNames() As String = Roles.GetAllRoles() 
     UsersRoleList.DataSource = roleNames 
     UsersRoleList.DataBind() 
 
     RoleList.DataSource = roleNames 
     RoleList.DataBind() 
End Sub

Se han agregado las dos últimas líneas del BindRolesToList método para enlazar el conjunto de roles al RoleList control DropDownList. En la figura 5 se muestra el resultado final cuando se ve a través de un explorador: una lista desplegable rellenada con los roles del sistema.

The Roles are Displayed in the RoleList DropDownList

Figura 5: Los roles se muestran en la DropDownList RoleList (haga clic para ver la imagen de tamaño completo)

Mostrar los usuarios que pertenecen al rol seleccionado

Cuando la página se carga por primera vez, o cuando se selecciona un nuevo rol en DropDownList RoleList, es necesario mostrar la lista de usuarios que pertenecen a ese rol en GridView. Cree un método denominado DisplayUsersBelongingToRole con el código siguiente:

Private Sub DisplayUsersBelongingToRole() 
     ' Get the selected role 
     Dim selectedRoleName As String = RoleList.SelectedValue 
 
     ' Get the list of usernames that belong to the role 
     Dim usersBelongingToRole() As String = Roles.GetUsersInRole(selectedRoleName) 
 
     ' Bind the list of users to the GridView 
     RolesUserList.DataSource = usersBelongingToRole 
     RolesUserList.DataBind() 
End Sub

Este método comienza obteniendo el rol seleccionado de RoleList DropDownList. A continuación, usa el Roles.GetUsersInRole(roleName) método para recuperar una matriz de cadenas de los UserNames de los usuarios que pertenecen a ese rol. A continuación, esta matriz se enlaza a RolesUserList GridView.

Este método debe llamarse en dos circunstancias: cuando la página se carga inicialmente y cuando cambia el rol seleccionado en DropDownList RoleList. Por lo tanto, actualice el Page_Load controlador de eventos para que este método se invoque después de la llamada a CheckRolesForSelectedUser. A continuación, cree un controlador de eventos para el RoleListevento de SelectedIndexChanged y llame a este método desde allí también.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     If Not Page.IsPostBack Then 
          ' Bind the users and roles 
          BindUsersToUserList() 
          BindRolesToList() 
 
          ' Check the selected user's roles 
          CheckRolesForSelectedUser() 
 
          'Display those users belonging to the currently selected role 
          DisplayUsersBelongingToRole() 
     End If 
End Sub 
 
... 
 
Protected Sub RoleList_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles RoleList.SelectedIndexChanged 
     DisplayUsersBelongingToRole() 
End Sub

Con este código implementado, GridView RolesUserList debe mostrar los usuarios que pertenecen al rol seleccionado. Como se muestra en la figura 6, el rol Supervisores consta de dos miembros: Bruce y Tito.

The GridView Lists Those Users That Belong to the Selected Role

Figura 6: GridView enumera los usuarios que pertenecen al rol seleccionado (haga clic para ver la imagende tamaño completo)

Quitar usuarios del rol seleccionado

Vamos a aumentar GridView RolesUserList para que incluya una columna de botones "Quitar". Al hacer clic en el botón "Quitar" de un usuario determinado, se quitarán de ese rol.

Empiece agregando un campo de botón Eliminar a GridView. Haga que este campo aparezca como el más archivado a la izquierda y cambie su DeleteText propiedad de "Delete" (valor predeterminado) a "Remove".

Screenshot that shows how to add the “Remove” button in the Fields window.

Figura 7: Agregar el botón "Quitar" a GridView (Haga clic para ver la imagende tamaño completo)

Cuando se hace clic en el botón "Quitar" se produce una devolución de postback y se genera el evento de RowDeleting GridView. Es necesario crear un controlador de eventos para este evento y escribir código que quite al usuario del rol seleccionado. A continuación, cree el controlador de eventos y agregue el código siguiente:

Protected Sub RolesUserList_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles RolesUserList.RowDeleting 
     ' Get the selected role 
     Dim selectedRoleName As String = RoleList.SelectedValue 
 
     ' Reference the UserNameLabel 
     Dim UserNameLabel As Label = CType(RolesUserList.Rows(e.RowIndex).FindControl("UserNameLabel"),Label) 
 
     ' Remove the user from the role 
     Roles.RemoveUserFromRole(UserNameLabel.Text, selectedRoleName) 
 
     ' Refresh the GridView 
     DisplayUsersBelongingToRole() 
 
     ' Display a status message 
     ActionStatus.Text = String.Format("User {0} was removed from role {1}.", UserNameLabel.Text,selectedRoleName) 
End Sub

El código comienza por determinar el nombre del rol seleccionado. A continuación, hace referencia mediante programación al UserNameLabel control de la fila cuyo botón "Quitar" se hizo clic para determinar el nombre de usuario del usuario que se va a quitar. A continuación, el usuario se quita del rol a través de una llamada al Roles.RemoveUserFromRole método. A RolesUserList continuación, GridView se actualiza y se muestra un mensaje a través del ActionStatus control Etiqueta.

Nota:

El botón "Quitar" no requiere ninguna confirmación del usuario antes de quitar el usuario del rol. Te invitamos a agregar algún nivel de confirmación de usuario. Una de las formas más fáciles de confirmar una acción es a través de un cuadro de diálogo confirmar del lado cliente. Para obtener más información sobre esta técnica, vea Agregar confirmación del lado cliente al eliminar.

En la figura 8 se muestra la página después de que el usuario Tito se haya quitado del grupo Supervisores.

Alas, Tito is No Longer a Supervisor

Figura 8: Alas, Tito ya no es supervisor (haga clic para ver la imagen de tamaño completo)

Agregar nuevos usuarios al rol seleccionado

Junto con la eliminación de usuarios del rol seleccionado, el visitante a esta página también debería poder agregar un usuario al rol seleccionado. La mejor interfaz para agregar un usuario al rol seleccionado depende del número de cuentas de usuario que espera tener. Si su sitio web hospedará solo unas docenas de cuentas de usuario o menos, puede usar un DropDownList aquí. Si puede haber miles de cuentas de usuario, querrá incluir una interfaz de usuario que permita al visitante paginar a través de las cuentas, buscar una cuenta determinada o filtrar las cuentas de usuario de alguna otra manera.

Para esta página, vamos a usar una interfaz muy sencilla que funcione independientemente del número de cuentas de usuario del sistema. Es decir, usaremos un TextBox, que pide al visitante que escriba el nombre de usuario del usuario que quiere agregar al rol seleccionado. Si no existe ningún usuario con ese nombre o si el usuario ya es miembro del rol, mostraremos un mensaje en Etiqueta ActionStatus. Pero si el usuario existe y no es miembro del rol, los agregaremos al rol y actualizaremos la cuadrícula.

Agregue un cuadro de texto y un botón debajo de GridView. Establezca el control TextBox ID en UserNameToAddToRole y establezca las propiedades ID y Text del botón en AddUserToRoleButton y "Agregar usuario a rol", respectivamente.

<p> 
     <b>UserName:</b> 
     <asp:TextBox ID="UserNameToAddToRole" runat="server"></asp:TextBox> 
     <br /> 
     <asp:Button ID="AddUserToRoleButton" runat="server" Text="Add User to Role" /> 
</p>

Cree un controlador de eventos Click para el botón AddUserToRoleButton y agregue el código siguiente:

Protected Sub AddUserToRoleButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles AddUserToRoleButton.Click 
     ' Get the selected role and username 
     Dim selectedRoleName As String = RoleList.SelectedValue 
     Dim userToAddToRole As String = UserNameToAddToRole.Text 
 
     ' Make sure that a value was entered 
     If userToAddToRole.Trim().Length = 0 Then 
          ActionStatus.Text = "You must enter a username in the textbox." 
          Exit Sub 
     End If 
 
     ' Make sure that the user exists in the system 
     Dim userInfo As MembershipUser = Membership.GetUser(userToAddToRole) 
     If userInfo Is Nothing Then 
          ActionStatus.Text = String.Format("The user {0} does not exist in the system.",userNameToAddToRole) 
          Exit Sub 
     End If 
 
     ' Make sure that the user doesn't already belong to this role 
     If Roles.IsUserInRole(userToAddToRole, selectedRoleName) Then 
          ActionStatus.Text = String.Format("User {0} already is a member of role {1}.", UserNameToAddToRole,selectedRoleName) 
          Exit Sub 
     End If 
 
     ' If we reach here, we need to add the user to the role 
     Roles.AddUserToRole(userToAddToRole, selectedRoleName) 
 
     ' Clear out the TextBox 
     userNameToAddToRole.Text = String.Empty 
 
     ' Refresh the GridView 
     DisplayUsersBelongingToRole() 
 
     ' Display a status message 
     ActionStatus.Text = String.Format("User {0} was added to role {1}.", UserNameToAddToRole,selectedRoleName) 
End Sub

La mayoría del código del Click controlador de eventos realiza varias comprobaciones de validación. Garantiza que el visitante proporcionó un nombre de usuario en TextBox UserNameToAddToRole, que el usuario existe en el sistema y que aún no pertenecen al rol seleccionado. Si se produce un error en cualquiera de estas comprobaciones, se muestra un mensaje adecuado en ActionStatus y se cierra el controlador de eventos. Si se pasan todas las comprobaciones, el usuario se agrega al rol a través del Roles.AddUserToRole método. Después de eso, se borra la propiedad TextBox Text, se actualiza GridView y la ActionStatus etiqueta muestra un mensaje que indica que el usuario especificado se agregó correctamente al rol seleccionado.

Nota:

Para asegurarse de que el usuario especificado aún no pertenece al rol seleccionado, usamos el Roles.IsUserInRole(userName, roleName) método, que devuelve un valor booleano que indica si userName es miembro de roleName. Usaremos este método de nuevo en el siguiente tutorial cuando examinemos la autorización basada en roles.

Visite la página a través de un explorador y seleccione el rol Supervisors en DropDownList RoleList. Intente escribir un nombre de usuario no válido: debería ver un mensaje que explique que el usuario no existe en el sistema.

You Cannot Add a Non-Existent User to a Role

Figura 9: No se puede agregar un usuario no existente a un rol (haga clic para ver la imagende tamaño completo)

Ahora intente agregar un usuario válido. Continúe y vuelva a agregar Tito al rol supervisores.

Tito Is Once Again a Supervisor!

Figura 10: Tito es una vez más supervisor! (Haga clic para ver la imagen a tamaño completo.)

Paso 3: Actualización cruzada de las interfaces "By User" y "By Role"

La UsersAndRoles.aspx página ofrece dos interfaces distintas para administrar usuarios y roles. Actualmente, estas dos interfaces actúan independientemente entre sí, por lo que es posible que un cambio realizado en una interfaz no se refleje inmediatamente en la otra. Por ejemplo, imagine que el visitante de la página selecciona el rol Supervisores de DropDownList RoleList, que enumera Bruce y Tito como sus miembros. A continuación, el visitante selecciona Tito en DropDownList UserList, que comprueba las casillas Administradores y Supervisores en el UsersRoleList Repetidor. Si el visitante desactiva el rol supervisor del repetidor, Tito se quita del rol supervisor, pero esta modificación no se refleja en la interfaz "por rol". GridView seguirá mostrando a Tito como miembro del rol Supervisores.

Para corregir esto, es necesario actualizar GridView siempre que se compruebe o desactive un rol del UsersRoleList repetidor. Del mismo modo, es necesario actualizar repeater cada vez que se quita o se agrega un usuario a un rol de la interfaz "by role".

El repetidor de la interfaz "por usuario" se actualiza llamando al CheckRolesForSelectedUser método. La interfaz "por rol" se puede modificar en el RolesUserList controlador de eventos de RowDeleting GridView y en el AddUserToRoleButton controlador de eventos del Click botón. Por lo tanto, es necesario llamar al CheckRolesForSelectedUser método desde cada uno de estos métodos.

Protected Sub RolesUserList_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles RolesUserList.RowDeleting 
     ... Code removed for brevity ... 
 
     ' Refresh the "by user" interface 
     CheckRolesForSelectedUser() 
End Sub 
 
Protected Sub AddUserToRoleButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles AddUserToRoleButton.Click 
     ... Code removed for brevity ... 
 
     ' Refresh the "by user" interface 
     CheckRolesForSelectedUser() 
End Sub

Del mismo modo, GridView en la interfaz "por rol" se actualiza llamando al DisplayUsersBelongingToRole método y la interfaz "by user" se modifica a través del RoleCheckBox_CheckChanged controlador de eventos. Por lo tanto, es necesario llamar al DisplayUsersBelongingToRole método desde este controlador de eventos.

Protected Sub RoleCheckBox_CheckChanged(ByVal sender As Object, ByVal e As EventArgs) 
     ... Code removed for brevity ... 
 
     ' Refresh the "by role" interface 
     DisplayUsersBelongingToRole() 
End Sub

Con estos cambios de código menores, las interfaces "por usuario" y "por rol" ahora se actualizan correctamente. Para comprobarlo, visite la página a través de un explorador y seleccione Tito y Supervisores en y UserListRoleList DropDownLists, respectivamente. Tenga en cuenta que, a medida que desactive el rol Supervisores para Tito desde el Repetidor en la interfaz "por usuario", Tito se quita automáticamente de GridView en la interfaz "por rol". Al volver a agregar Tito al rol Supervisores desde la interfaz "por rol" se vuelve a comprobar automáticamente la casilla Supervisores en la interfaz "by user".

Paso 4: Personalizar CreateUserWizard para incluir un paso "Especificar roles"

En el tutorial Creación de cuentas de usuario hemos visto cómo usar el control Web CreateUserWizard para proporcionar una interfaz para crear una nueva cuenta de usuario. El control CreateUserWizard se puede usar de una de estas dos maneras:

  • Como medio para que los visitantes creen su propia cuenta de usuario en el sitio, y
  • Como medio para que los administradores creen nuevas cuentas

En el primer caso de uso, un visitante llega al sitio y rellena el CreateUserWizard, escribiendo su información para registrarse en el sitio. En el segundo caso, un administrador crea una nueva cuenta para otra persona.

Cuando un administrador crea una cuenta para otra persona, puede resultar útil permitir al administrador especificar a qué roles pertenece la nueva cuenta de usuario. En el tutorial Almacenarinformación de usuario adicional, vimos cómo personalizar CreateUserWizard agregando más WizardSteps. Veamos cómo agregar un paso adicional a CreateUserWizard para especificar los roles del nuevo usuario.

Abra la CreateUserWizardWithRoles.aspx página y agregue un control CreateUserWizard denominado RegisterUserWithRoles. Establezca la propiedad del ContinueDestinationPageUrl control en "~/Default.aspx". Dado que la idea aquí es que un administrador usará este control CreateUserWizard para crear nuevas cuentas de usuario, establezca la propiedad del LoginCreatedUser control en False. Esta LoginCreatedUser propiedad especifica si el visitante inicia sesión automáticamente como el usuario recién creado y el valor predeterminado es True. Lo establecemos en False porque cuando un administrador crea una nueva cuenta, queremos mantenerla iniciada como él mismo.

A continuación, seleccione "Agregar o quitar WizardSteps..." opción de la etiqueta inteligente CreateUserWizard y agregue un nuevo WizardStep, estableciendo en IDSpecifyRolesStep. Mueva el SpecifyRolesStep WizardStep para que llegue después del paso "Suscribirse a su nueva cuenta", pero antes del paso "Completar". Establezca la propiedad de en WizardStepTitle "Especificar roles", su StepType propiedad Stepen y su AllowReturn propiedad en False.

Screenshot that shows the selected Specify Roles properties in the Wizard Step Collection Editor window.

Figura 11: Agregar "Especificar roles" WizardStep a CreateUserWizard (Haga clic para ver la imagen de tamaño completo)

Después de este cambio, el marcado declarativo de CreateUserWizard debe ser similar al siguiente:

<asp:CreateUserWizard ID="RegisterUserWithRoles" runat="server" 
     ContinueDestinationPageUrl="~/Default.aspx" LoginCreatedUser="False"> 
     <WizardSteps> 
          <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server"> 
          </asp:CreateUserWizardStep> 
          <asp:WizardStep ID="SpecifyRolesStep" runat="server" StepType="Step" 
               Title="Specify Roles" AllowReturn="False"> 
          </asp:WizardStep> 
          <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server"> 
          </asp:CompleteWizardStep> 
     </WizardSteps> 
</asp:CreateUserWizard>

En "Especificar roles", WizardStepagregue un CheckBoxList denominado RoleList. This CheckBoxList will list the available roles, lo que permite a la persona que visita la página comprobar a qué roles pertenece el usuario recién creado.

Nos quedamos con dos tareas de codificación: primero debemos rellenar CheckBoxList RoleList con los roles del sistema; en segundo lugar, es necesario agregar el usuario creado a los roles seleccionados cuando el usuario pasa del paso "Especificar roles" al paso "Completar". Podemos realizar la primera tarea en el controlador de Page_Load eventos. El código siguiente hace referencia mediante programación a CheckBox RoleList en la primera visita a la página y enlaza los roles del sistema a él.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     If Not Page.IsPostBack Then 
          ' Reference the SpecifyRolesStep WizardStep 
          Dim SpecifyRolesStep As WizardStep = CType(RegisterUserWithRoles.FindControl("SpecifyRolesStep"),WizardStep) 
 
          ' Reference the RoleList CheckBoxList 
          Dim RoleList As CheckBoxList = CType(SpecifyRolesStep.FindControl("RoleList"), CheckBoxList) 
 
          ' Bind the set of roles to RoleList 
          RoleList.DataSource = Roles.GetAllRoles() 
          RoleList.DataBind() 
     End If 
End Sub

El código anterior debe ser familiar. En el tutorial Almacenarinformación adicional de usuario hemos usado dos FindControl instrucciones para hacer referencia a un control web desde un personalizado WizardStep. Y el código que enlaza los roles a CheckBoxList se tomó anteriormente en este tutorial.

Para realizar la segunda tarea de programación, es necesario saber cuándo se ha completado el paso "Especificar roles". Recuerde que CreateUserWizard tiene un ActiveStepChanged evento, que se desencadena cada vez que el visitante navega de un paso a otro. Aquí podemos determinar si el usuario ha alcanzado el paso "Completar"; si es así, es necesario agregar el usuario a los roles seleccionados.

Cree un controlador de eventos para el evento de ActiveStepChanged y agregue el código siguiente al controlador:

Protected Sub RegisterUserWithRoles_ActiveStepChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles RegisterUserWithRoles.ActiveStepChanged 
     'Have we JUST reached the Complete step? 
     If RegisterUserWithRoles.ActiveStep.Title = "Complete" Then 
          ' Reference the SpecifyRolesStep WizardStep 
          Dim SpecifyRolesStep As WizardStep = CType(RegisterUserWithRoles.FindControl("SpecifyRolesStep"),WizardStep) 
 
          ' Reference the RoleList CheckBoxList 
          Dim RoleList As CheckBoxList = CType(SpecifyRolesStep.FindControl("RoleList"), CheckBoxList) 
 
          ' Add the checked roles to the just-added user 
          For Each li As ListItem In RoleList.Items 
               If li.Selected Then 
                    Roles.AddUserToRole(RegisterUserWithRoles.UserName, li.Text) 
               End If 
          Next 
     End If 
End Sub

Si el usuario acaba de alcanzar el paso "Completado", el controlador de eventos enumera los elementos de RoleList CheckBoxList y el usuario recién creado se asigna a los roles seleccionados.

Ahora pruebe esta página a través de un explorador. El primer paso de CreateUserWizard es el paso estándar "Suscribirse a su nueva cuenta", que solicita el nombre de usuario, la contraseña, el correo electrónico y otra información clave del nuevo usuario. Escriba la información para crear un nuevo usuario denominado Wanda.

Create a New User Named Wanda

Figura 12: Crear un nuevo usuario denominado Wanda (haga clic para ver la imagende tamaño completo)

Haga clic en el botón Crear usuario. CreateUserWizard llama internamente al Membership.CreateUser método, crea la nueva cuenta de usuario y, a continuación, avanza al paso siguiente, "Especificar roles". Aquí se enumeran los roles del sistema. Active la casilla Supervisores y haga clic en Siguiente.

Make Wanda a Member of the Supervisors Role

Figura 13: Hacer que Wanda sea miembro del rol supervisores (haga clic para ver la imagende tamaño completo)

Al hacer clic en Siguiente, se produce un postback y se actualiza el ActiveStep al paso "Completar". En el ActiveStepChanged controlador de eventos, la cuenta de usuario creada recientemente se asigna al rol Supervisores. Para comprobarlo, vuelva a la UsersAndRoles.aspx página y seleccione Supervisors en DropDownList RoleList. Como se muestra en la figura 14, los supervisores ahora están formados por tres usuarios: Bruce, Tito y Wanda.

Bruce, Tito, and Wanda are All Supervisors

Figura 14: Bruce, Tito y Wanda son Todos los Supervisores (Haga clic para ver la imagende tamaño completo)

Resumen

El marco roles ofrece métodos para recuperar información sobre los roles y métodos de un usuario determinado para determinar qué usuarios pertenecen a un rol especificado. Además, hay varios métodos para agregar y quitar uno o varios usuarios a uno o varios roles. En este tutorial nos centramos en solo dos de estos métodos: AddUserToRole y RemoveUserFromRole. Hay variantes adicionales diseñadas para agregar varios usuarios a un solo rol y asignar varios roles a un único usuario.

En este tutorial también se ha incluido un vistazo a la extensión del control CreateUserWizard para incluir para WizardStep especificar los roles del usuario recién creados. Este paso podría ayudar a un administrador a simplificar el proceso de creación de cuentas de usuario para nuevos usuarios.

En este punto hemos visto cómo crear y eliminar roles y cómo agregar y quitar usuarios de roles. Pero todavía tenemos que examinar la aplicación de la autorización basada en roles. En el siguiente tutorial veremos cómo definir reglas de autorización de direcciones URL por rol, así como cómo limitar la funcionalidad de nivel de página en función de los roles del usuario que ha iniciado sesión actualmente.

¡Feliz programación!

Lecturas adicionales

Para obtener más información sobre los temas tratados en este tutorial, consulte los siguientes recursos:

Acerca del autor

Scott Mitchell, autor de varios libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Se puede contactar con Scott en mitchell@4guysfromrolla.com o a través de su blog en http://ScottOnWriting.NET.

Agradecimientos especiales a...

Muchos revisores han evaluado esta serie de tutoriales. El revisor principal de este tutorial fue Teresa Murphy. ¿Le interesaría revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com