Condividi tramite


Assegnazione di ruoli agli utenti (C#)

di Scott Mitchell

Nota

Poiché questo articolo è stato scritto, i provider di appartenenza ASP.NET sono stati sostituiti da ASP.NET Identity. È consigliabile aggiornare le app per usare la ASP.NET Identity Platform anziché i provider di appartenenza in primo piano al momento della scrittura di questo articolo. ASP.NET Identity offre numerosi vantaggi rispetto al sistema di appartenenza ASP.NET, tra cui :

  • Prestazioni migliori
  • Miglioramento dell'estendibilità e della testability
  • Supporto per OAuth, OpenID Connect e autenticazione a due fattori
  • Supporto delle identità basate sulle attestazioni
  • Interoperabilità migliore con ASP.Net Core

Scaricare codice o scaricare pdf

In questa esercitazione verranno compilate due pagine ASP.NET per facilitare la gestione di quali ruoli appartengono gli utenti. La prima pagina includerà le funzionalità per vedere quali utenti appartengono a un determinato ruolo, quali ruoli appartiene a un determinato utente e la possibilità di assegnare o rimuovere un determinato utente da un determinato ruolo. Nella seconda pagina verrà incrementato il controllo CreateUserWizard in modo che includa un passaggio per specificare i ruoli a cui appartiene l'utente appena creato. Questo è utile negli scenari in cui un amministratore è in grado di creare nuovi account utente.

Introduzione

L'esercitazione precedente ha esaminato il framework Ruoli e l'oggetto SqlRoleProvider. È stato illustrato come usare la Roles classe per creare, recuperare ed eliminare ruoli. Oltre a creare ed eliminare ruoli, è necessario essere in grado di assegnare o rimuovere utenti da un ruolo. Sfortunatamente, ASP.NET non viene fornito con alcun controllo Web per gestire gli utenti che appartengono ai ruoli. È invece necessario creare pagine di ASP.NET personalizzate per gestire queste associazioni. La buona notizia è che l'aggiunta e la rimozione degli utenti ai ruoli è piuttosto facile. La Roles classe contiene diversi metodi per l'aggiunta di uno o più utenti a uno o più ruoli.

In questa esercitazione verranno compilate due pagine ASP.NET per facilitare la gestione di quali ruoli appartengono gli utenti. La prima pagina includerà le funzionalità per vedere quali utenti appartengono a un determinato ruolo, quali ruoli appartiene a un determinato utente e la possibilità di assegnare o rimuovere un determinato utente da un determinato ruolo. Nella seconda pagina verrà incrementato il controllo CreateUserWizard in modo che includa un passaggio per specificare i ruoli a cui appartiene l'utente appena creato. Questo è utile negli scenari in cui un amministratore è in grado di creare nuovi account utente.

È possibile iniziare subito.

Elencare quali utenti appartengono ai ruoli

Il primo ordine aziendale per questa esercitazione consiste nel creare una pagina Web da cui gli utenti possono essere assegnati ai ruoli. Prima di preoccuparsi di come assegnare utenti ai ruoli, è prima necessario concentrarsi su come determinare quali utenti appartengono ai ruoli. Esistono due modi per visualizzare queste informazioni: "per ruolo" o "per utente". È possibile consentire al visitatore di selezionare un ruolo e quindi visualizzarli tutti gli utenti che appartengono al ruolo (la visualizzazione "per ruolo") oppure è possibile richiedere al visitatore di selezionare un utente e quindi visualizzarli i ruoli assegnati all'utente (visualizzazione "by user").

La visualizzazione "per ruolo" è utile in circostanze in cui il visitatore vuole conoscere il set di utenti che appartengono a un determinato ruolo; la visualizzazione "by user" è ideale quando il visitatore deve conoscere i ruoli di un determinato utente. La pagina include le interfacce "per ruolo" e "per utente".

Si inizierà con la creazione dell'interfaccia "by user". Questa interfaccia sarà costituita da un elenco a discesa e da un elenco di caselle di controllo. L'elenco a discesa verrà popolato con il set di utenti nel sistema; le caselle di controllo enumereranno i ruoli. Selezionando un utente dall'elenco a discesa verranno controllati i ruoli a cui appartiene l'utente. La persona che visita la pagina può quindi selezionare o deselezionare le caselle di controllo per aggiungere o rimuovere l'utente selezionato dai ruoli corrispondenti.

Nota

L'uso di un elenco a discesa per elencare gli account utente non è una scelta ideale per i siti Web in cui potrebbero esserci centinaia di account utente. Un elenco a discesa è progettato per consentire a un utente di selezionare un elemento da un elenco relativamente breve di opzioni. Diventa rapidamente unwieldy quando il numero di elementi dell'elenco aumenta. Se si sta creando un sito Web che avrà potenzialmente un numero elevato di account utente, è possibile considerare l'uso di un'interfaccia utente alternativa, ad esempio un'interfaccia GridView paginabile o un'interfaccia filtrabile che richiede al visitatore di scegliere una lettera e quindi mostra solo gli utenti il cui nome utente inizia con la lettera selezionata.

Passaggio 1: Creazione dell'interfaccia utente "By User"

Aprire la UsersAndRoles.aspx pagina. Nella parte superiore della pagina aggiungere un controllo Web etichetta denominato ActionStatus e cancellarne la Text proprietà. Questa etichetta verrà usata per fornire commenti e suggerimenti sulle azioni eseguite, visualizzando messaggi come "User Tito è stato aggiunto al ruolo Administrators" o "User Jisun è stato rimosso dal ruolo Supervisori". Per rendere questi messaggi importanti, impostare la proprietà dell'etichetta CssClass su "Importante".

<p align="center"> 

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

Aggiungere quindi la definizione della classe CSS seguente al Styles.css foglio di stile:

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

Questa definizione CSS indica al browser di visualizzare l'etichetta usando un carattere rosso di grandi dimensioni. La figura 1 mostra questo effetto tramite la Designer di Visual Studio.

La proprietà CssClass dell'etichetta genera un carattere rosso di grandi dimensioni

Figura 1: La proprietà dell'etichetta CssClass restituisce un carattere rosso di grandi dimensioni (fare clic per visualizzare un'immagine full-size)

Aggiungere quindi un oggetto DropDownList alla pagina, impostarne la proprietà su UserListe impostarne la AutoPostBackID proprietà su True. Questo elenco a discesa verrà usato per elencare tutti gli utenti nel sistema. Questo elenco a discesa verrà associato a una raccolta di oggetti MembershipUser. Poiché si vuole che DropDownList visualizzi la proprietà UserName dell'oggetto MembershipUser (e usarla come valore degli elementi dell'elenco DataTextField ), impostare le proprietà e DataValueField di DropDownList su "UserName".

Sotto l'elenco a discesa aggiungere un ripetitore denominato UsersRoleList. Questo ripetitore elenca tutti i ruoli nel sistema come serie di caselle di controllo. Definire il markup dichiarativo seguente tramite ItemTemplate il ripetitore:

<asp:Repeater ID="UsersRoleList" runat="server"> 
     <ItemTemplate> 
          <asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true" 

               Text='<%# Container.DataItem %>' /> 
          <br /> 
     </ItemTemplate> 
</asp:Repeater>

Il ItemTemplate markup include un singolo controllo Web CheckBox denominato RoleCheckBox. La proprietà CheckBox AutoPostBack è impostata su True e la Text proprietà è associata a Container.DataItem. Il motivo per cui la sintassi databinding è semplicemente Container.DataItem perché il framework Ruoli restituisce l'elenco di nomi di ruolo come matrice di stringhe ed è questa matrice di stringhe che verrà associata al ripetitore. Una descrizione approfondita del motivo per cui questa sintassi viene usata per visualizzare il contenuto di una matrice associata a un controllo Web dati oltre l'ambito di questa esercitazione. Per altre informazioni su questa questione, vedere Associazione di una matrice scalare a un controllo Web dati.

A questo punto il markup dichiarativo dell'interfaccia "by user" dovrebbe essere simile al seguente:

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

È ora possibile scrivere il codice per associare il set di account utente a DropDownList e al set di ruoli al ripetitore. Nella classe code-behind della pagina aggiungere un metodo denominato e un altro denominato BindUsersToUserListBindRolesListusando il codice seguente:

private void BindUsersToUserList() 
{ 
     // Get all of the user accounts 
     MembershipUserCollection users = Membership.GetAllUsers(); 
     UserList.DataSource = users; 
     UserList.DataBind(); 
}
 
private void BindRolesToList() 
{ 
     // Get all of the roles 
     string[] roles = Roles.GetAllRoles(); 
     UsersRoleList.DataSource = roles; 
     UsersRoleList.DataBind(); 
}

Il BindUsersToUserList metodo recupera tutti gli account utente nel sistema tramite il Membership.GetAllUsers metodo . Restituisce un MembershipUserCollection oggetto, ovvero una raccolta di MembershipUser istanze. Questa raccolta viene quindi associata a UserList DropDownList. Le MembershipUser istanze che trucco la raccolta contengono una varietà di proprietà, ad esempio UserName, EmailCreationDate, e IsOnline. Per indicare a DropDownList di visualizzare il valore della UserName proprietà, assicurarsi che le UserList proprietà e DataValueField di DropDownList DataTextField siano state impostate su "UserName".

Nota

Il Membership.GetAllUsers metodo include due overload: uno che non accetta parametri di input e restituisce tutti gli utenti e uno che accetta valori interi per l'indice di pagina e le dimensioni della pagina e restituisce solo il subset specificato degli utenti. Quando ci sono grandi quantità di account utente visualizzati in un elemento dell'interfaccia utente paginabile, il secondo overload può essere usato per paginare in modo più efficiente gli utenti perché restituisce solo il subset preciso degli account utente anziché tutti.

Il BindRolesToList metodo inizia chiamando il Roles metodo della GetAllRolesclasse, che restituisce una matrice di stringhe contenente i ruoli nel sistema. Questa matrice di stringhe viene quindi associata al ripetitore.

Infine, è necessario chiamare questi due metodi quando la pagina viene prima caricata. Aggiungere il codice seguente al gestore eventi Page_Load :

protected void Page_Load(object sender, EventArgs e) 
{ 
     if (!Page.IsPostBack) 
     { 
          // Bind the users and roles 
          BindUsersToUserList(); 
          BindRolesToList(); 
     } 
}

Con questo codice sul posto, visitare la pagina tramite un browser; la schermata dovrebbe essere simile alla figura 2. Tutti gli account utente vengono popolati nell'elenco a discesa e, sotto di essi, ogni ruolo viene visualizzato come casella di controllo. Poiché vengono impostate le AutoPostBack proprietà di DropDownList e CheckBox su True, la modifica dell'utente selezionato o il controllo o la deselezionazione di un ruolo causa un postback. Non viene eseguita alcuna azione, tuttavia, perché è ancora necessario scrivere codice per gestire queste azioni. Queste attività verranno affrontate nelle due sezioni successive.

La pagina visualizza gli utenti e i ruoli

Figura 2: la pagina visualizza gli utenti e i ruoli (fare clic per visualizzare l'immagine full-size)

Controllo dei ruoli a cui appartiene l'utente selezionato

Quando la pagina viene prima caricata o ogni volta che il visitatore seleziona un nuovo utente dall'elenco a discesa, è necessario aggiornare le UsersRoleListcaselle di controllo 's in modo che venga selezionata una determinata casella di controllo ruolo solo se l'utente selezionato appartiene a tale ruolo. A tale scopo, creare un metodo denominato CheckRolesForSelectedUser con il codice seguente:

private void CheckRolesForSelectedUser() 
{ 
     // Determine what roles the selected user belongs to 
     string selectedUserName = UserList.SelectedValue; 
     string[] selectedUsersRoles = Roles.GetRolesForUser(selectedUserName); 

     // Loop through the Repeater's Items and check or uncheck the checkbox as needed 

     foreach (RepeaterItem ri in UsersRoleList.Items) 
     { 
          // Programmatically reference the CheckBox 
          CheckBox RoleCheckBox = ri.FindControl("RoleCheckBox") as CheckBox; 
          // See if RoleCheckBox.Text is in selectedUsersRoles 
          if (selectedUsersRoles.Contains<string>(RoleCheckBox.Text)) 
               RoleCheckBox.Checked = true; 
          else 
               RoleCheckBox.Checked = false; 
     } 
}

Il codice precedente inizia determinando chi è l'utente selezionato. Usa quindi il metodo della GetRolesForUser(userName) classe Roles per restituire il set di ruoli dell'utente specificato come matrice di stringhe. Successivamente, gli elementi del ripetitore vengono enumerati e ogni casella di controllo di ogni elemento viene fatto riferimento a livello di RoleCheckBox codice. CheckBox viene selezionato solo se il ruolo corrispondente è contenuto all'interno della selectedUsersRoles matrice di stringhe.

Nota

La selectedUserRoles.Contains<string>(...) sintassi non verrà compilata se si usa ASP.NET versione 2.0. Il Contains<string> metodo fa parte della libreria LINQ, che è una novità di ASP.NET 3.5. Se si usa ancora ASP.NET versione 2.0, usare invece il Array.IndexOf<string> metodo .

Il CheckRolesForSelectedUser metodo deve essere chiamato in due casi: quando la pagina viene caricata per la prima volta e ogni volta che viene modificato l'indice UserList selezionato di DropDownList. Chiamare quindi questo metodo dal Page_Load gestore eventi (dopo le chiamate a BindUsersToUserList e BindRolesToList). Creare anche un gestore eventi per l'evento SelectedIndexChanged DropDownList e chiamare questo metodo da questa posizione.

protected void Page_Load(object sender, EventArgs e) 
{ 
     if (!Page.IsPostBack) 
     { 

          // Bind the users and roles 
          BindUsersToUserList(); 
          BindRolesToList(); 
          // Check the selected user's roles 
          CheckRolesForSelectedUser(); 
     } 
} 

... 

protected void UserList_SelectedIndexChanged(object sender, EventArgs e) 
{ 
     CheckRolesForSelectedUser(); 
}

Con questo codice sul posto, è possibile testare la pagina tramite il browser. Tuttavia, poiché la UsersAndRoles.aspx pagina attualmente non ha la possibilità di assegnare utenti ai ruoli, nessun utente ha ruoli. Verrà creata l'interfaccia per l'assegnazione di utenti ai ruoli in un momento, quindi è possibile prendere la parola che il codice funziona e verificare che funzioni in un secondo momento oppure è possibile aggiungere manualmente utenti ai ruoli inserendo i record nella aspnet_UsersInRoles tabella per testare ora questa funzionalità.

Assegnazione e rimozione di utenti dai ruoli

Quando il visitatore controlla o deseleziona un controllo CheckBox nel UsersRoleList ripetitore, è necessario aggiungere o rimuovere l'utente selezionato dal ruolo corrispondente. La proprietà di AutoPostBack CheckBox è attualmente impostata su True, che causa un postback ogni volta che un controllo CheckBox nel ripetitore è selezionato o deselezionato. In breve, è necessario creare un gestore eventi per l'evento CheckChanged CheckBox. Poiché CheckBox si trova in un controllo Repeater, è necessario aggiungere manualmente l'impianto idraulico del gestore eventi. Per iniziare, aggiungere il gestore eventi alla classe code-behind come protected metodo, come illustrato di seguito:

protected void RoleCheckBox_CheckChanged(object sender, EventArgs e) 
{ 

}

Si tornerà a scrivere il codice per questo gestore eventi in un momento. Ma prima di tutto è necessario completare l'impianto idraulico per la gestione degli eventi. Dal controllo CheckBox all'interno di Repeater aggiungere ItemTemplateOnCheckedChanged="RoleCheckBox_CheckChanged". Questa sintassi collega il RoleCheckBox_CheckChanged gestore eventi all'evento dell'oggetto RoleCheckBoxCheckedChanged .

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

L'attività finale consiste nel completare il RoleCheckBox_CheckChanged gestore eventi. È necessario iniziare facendo riferimento al controllo CheckBox che ha generato l'evento perché questa istanza di CheckBox indica il ruolo selezionato o deselezionato tramite le Text relative proprietà e Checked . Usando queste informazioni insieme a UserName dell'utente selezionato, l'utente viene aggiunto o rimosso dal ruolo tramite il Roles metodo o RemoveUserFromRoledella AddUserToRole classe .

protected void RoleCheckBox_CheckChanged(object sender, EventArgs e) 
{ 
     // Reference the CheckBox that raised this event 
     CheckBox RoleCheckBox = sender as CheckBox; 

     // Get the currently selected user and role 
     string selectedUserName = UserList.SelectedValue; 

     string roleName = RoleCheckBox.Text; 

     // Determine if we need to add or remove the user from this role 
     if (RoleCheckBox.Checked) 
     { 
          // 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); 

     } 
}

Il codice precedente inizia facendo riferimento a livello di codice a CheckBox che ha generato l'evento, disponibile tramite il sender parametro di input. Se la casella di controllo è selezionata, l'utente selezionato viene aggiunto al ruolo specificato; in caso contrario, vengono rimossi dal ruolo. In entrambi i casi, l'etichetta ActionStatus visualizza un messaggio che riepiloga l'azione appena eseguita.

Prova questa pagina tramite un browser. Selezionare l'utente Tito e quindi aggiungere Tito ai ruoli Amministratori e Supervisori.

Tito è stato aggiunto ai ruoli amministratori e supervisori

Figura 3: Tito è stato aggiunto ai ruoli amministratori e supervisori (fare clic per visualizzare l'immagine a dimensione intera)

Selezionare quindi l'utente Bruce dall'elenco a discesa. È presente un postback e i checkBox del repeater vengono aggiornati tramite .CheckRolesForSelectedUser Poiché Bruce non appartiene ancora ad alcun ruolo, le due caselle di controllo sono deselezionate. Aggiungere quindi Bruce al ruolo Supervisori.

Bruce è stato aggiunto al ruolo supervisori

Figura 4: Bruce è stato aggiunto al ruolo Supervisori (fare clic per visualizzare l'immagine a dimensione intera)

Per verificare ulteriormente la funzionalità del CheckRolesForSelectedUser metodo, selezionare un utente diverso da Tito o Bruce. Si noti che le caselle di controllo vengono deselezionate automaticamente, indicando che non appartengono ad alcun ruolo. Torna a Tito. È necessario selezionare entrambe le caselle di controllo Amministratori e Supervisori.

Passaggio 2: Creazione dell'interfaccia utente "Per ruoli"

A questo punto è stata completata l'interfaccia "per utenti" e si è pronti per iniziare ad affrontare l'interfaccia "per ruoli". L'interfaccia "by roles" richiede all'utente di selezionare un ruolo da un elenco a discesa e quindi visualizza il set di utenti che appartengono a tale ruolo in un controllo GridView.

Aggiungere un altro controllo DropDownList alla UsersAndRoles.aspx pagina. Posizionare questo oggetto sotto il controllo Repeater, denominarlo RoleListe impostarne la AutoPostBack proprietà su True. Sotto di esso aggiungere un controllo GridView e denominarlo RolesUserList. Questo controllo GridView elenca gli utenti che appartengono al ruolo selezionato. Impostare la proprietà di AutoGenerateColumns GridView su False, aggiungere un Oggetto TemplateField all'insieme della Columns griglia e impostarne HeaderText la proprietà su "Users". Definire l'oggetto ItemTemplate TemplateField in modo che visualizzi il valore dell'espressione Container.DataItem databinding nella Text proprietà di un oggetto Label denominato UserNameLabel.

Dopo aver aggiunto e configurato GridView, il markup dichiarativo dell'interfaccia "per ruolo" dovrebbe essere simile al seguente:

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

È necessario popolare RoleList DropDownList con il set di ruoli nel sistema. A tale scopo, aggiornare il BindRolesToList metodo in modo che venga associata la matrice di stringhe restituita dal Roles.GetAllRoles metodo all'oggetto RolesList DropDownList e al UsersRoleList Repeater.

private void BindRolesToList() 
{ 
     // Get all of the roles 

     string[] roles = Roles.GetAllRoles(); 
     UsersRoleList.DataSource = roles; 
     UsersRoleList.DataBind(); 

     RoleList.DataSource = roles; 
     RoleList.DataBind(); 
}

Le ultime due righe del BindRolesToList metodo sono state aggiunte per associare il set di ruoli al RoleList controllo DropDownList. La figura 5 mostra il risultato finale quando visualizzato tramite un browser, ovvero un elenco a discesa popolato con i ruoli del sistema.

I ruoli vengono visualizzati nell'elenco a discesa RoleList

Figura 5: I ruoli vengono visualizzati nell'elenco RoleList a discesa (fare clic per visualizzare l'immagine a dimensione intera)

Visualizzazione degli utenti che appartengono al ruolo selezionato

Quando la pagina viene caricata per la prima volta o quando viene selezionato un nuovo ruolo da RoleList DropDownList, è necessario visualizzare l'elenco di utenti che appartengono a tale ruolo in GridView. Creare un metodo denominato DisplayUsersBelongingToRole usando il codice seguente:

private void DisplayUsersBelongingToRole() 
{ 
     // Get the selected role 
     string selectedRoleName = RoleList.SelectedValue; 

     // Get the list of usernames that belong to the role 
     string[] usersBelongingToRole = Roles.GetUsersInRole(selectedRoleName); 

     // Bind the list of users to the GridView 
     RolesUserList.DataSource = usersBelongingToRole; 
     RolesUserList.DataBind(); 
}

Questo metodo inizia ottenendo il ruolo selezionato da RoleList DropDownList. Usa quindi il Roles.GetUsersInRole(roleName) metodo per recuperare una matrice di stringhe degli utenti che appartengono a tale ruolo. Questa matrice viene quindi associata a RolesUserList GridView.

Questo metodo deve essere chiamato in due circostanze: quando la pagina viene inizialmente caricata e quando viene modificato il ruolo selezionato nell'elenco RoleList a discesa. Aggiornare quindi il Page_Load gestore eventi in modo che questo metodo venga richiamato dopo la chiamata a CheckRolesForSelectedUser. Successivamente, creare un gestore eventi per l'evento dell'oggetto RoleListSelectedIndexChanged e chiamare anche questo metodo da questa posizione.

protected void Page_Load(object sender, EventArgs e) 
{ 
     if (!Page.IsPostBack) 
     { 
          // Bind the users and roles 
          BindUsersToUserList(); 
          BindRolesToList(); 

          // Check the selected user's roles 
          CheckRolesForSelectedUser(); 

          // Display those users belonging to the currently selected role 
          DisplayUsersBelongingToRole(); 
     } 
} 

... 

protected void RoleList_SelectedIndexChanged(object sender, EventArgs e) 
{ 
     DisplayUsersBelongingToRole(); 
}

Con questo codice sul posto, RolesUserList GridView dovrebbe visualizzare gli utenti che appartengono al ruolo selezionato. Come illustrato nella figura 6, il ruolo Supervisori è costituito da due membri: Bruce e Tito.

GridView elenca gli utenti che appartengono al ruolo selezionato

Figura 6: GridView elenca gli utenti che appartengono al ruolo selezionato (fare clic per visualizzare l'immagine a dimensione intera)

Rimozione di utenti dal ruolo selezionato

È ora possibile aumentare RolesUserList GridView in modo che includa una colonna di pulsanti "Rimuovi". Facendo clic sul pulsante "Rimuovi" per un determinato utente verranno rimossi da tale ruolo.

Per iniziare, aggiungere un campo pulsante Elimina a GridView. Impostare questo campo come più a sinistra archiviato e modificarne la DeleteText proprietà da "Elimina" (impostazione predefinita) a "Rimuovi".

Screenshot che mostra come aggiungere il pulsante

Figura 7: Aggiungere il pulsante "Rimuovi" a GridView (fare clic per visualizzare l'immagine a dimensione intera)

Quando si fa clic sul pulsante "Rimuovi" viene eseguito un postback e viene generato l'evento gridView RowDeleting . È necessario creare un gestore eventi per questo evento e scrivere codice che rimuove l'utente dal ruolo selezionato. Creare il gestore eventi e quindi aggiungere il codice seguente:

protected void RolesUserList_RowDeleting(object sender, GridViewDeleteEventArgs e) 
{ 
     // Get the selected role 
     string selectedRoleName = RoleList.SelectedValue; 

     // Reference the UserNameLabel 
     Label UserNameLabel = RolesUserList.Rows[e.RowIndex].FindControl("UserNameLabel") as 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); 
}

Il codice inizia determinando il nome del ruolo selezionato. Fa quindi riferimento al UserNameLabel controllo dalla riga di cui è stato fatto clic sul pulsante "Rimuovi" per determinare il nome utente dell'utente da rimuovere. L'utente viene quindi rimosso dal ruolo tramite una chiamata al Roles.RemoveUserFromRole metodo . RolesUserList GridView viene quindi aggiornato e viene visualizzato un messaggio tramite il ActionStatus controllo Etichetta.

Nota

Il pulsante "Rimuovi" non richiede alcuna conferma da parte dell'utente prima di rimuovere l'utente dal ruolo. Vi invito ad aggiungere un certo livello di conferma dell'utente. Uno dei modi più semplici per confermare un'azione consiste nell'usare una finestra di dialogo di conferma sul lato client. Per altre informazioni su questa tecnica, vedere Aggiunta di Client-Side conferma durante l'eliminazione.

La figura 8 mostra la pagina dopo che l'utente Tito è stato rimosso dal gruppo Supervisors.

Ahimè, Tito non è più un supervisore

Figura 8: Alas, Tito non è più un supervisore (fare clic per visualizzare l'immagine a dimensione intera)

Aggiunta di nuovi utenti al ruolo selezionato

Insieme alla rimozione di utenti dal ruolo selezionato, il visitatore di questa pagina deve anche essere in grado di aggiungere un utente al ruolo selezionato. L'interfaccia migliore per l'aggiunta di un utente al ruolo selezionato dipende dal numero di account utente previsti. Se il tuo sito Web ospita solo poche decine di account utente o meno, puoi usare un elenco DropDownList qui. Se potrebbero essere presenti migliaia di account utente, è consigliabile includere un'interfaccia utente che consenta al visitatore di scorrere gli account, cercare un account specifico o filtrare gli account utente in qualche altro modo.

Per questa pagina si userà un'interfaccia molto semplice che funziona indipendentemente dal numero di account utente nel sistema. In genere, verrà usato un controllo TextBox, che richiede al visitatore di digitare il nome utente dell'utente che vuole aggiungere al ruolo selezionato. Se non esiste alcun utente con tale nome o se l'utente è già membro del ruolo, verrà visualizzato un messaggio in ActionStatus Etichetta. Tuttavia, se l'utente esiste e non è membro del ruolo, verranno aggiunti al ruolo e verrà aggiornata la griglia.

Aggiungere un controllo TextBox e Button sotto GridView. Impostare il controllo TextBox su IDUserNameToAddToRole e impostare le proprietà e Text del ID pulsante rispettivamente su AddUserToRoleButton e su "Aggiungi utente a ruolo".

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

Creare quindi un Click gestore eventi per AddUserToRoleButton e aggiungere il codice seguente:

protected void AddUserToRoleButton_Click(object sender, EventArgs e) 
{ 
     // Get the selected role and username 

     string selectedRoleName = RoleList.SelectedValue; 
     string userNameToAddToRole = UserNameToAddToRole.Text; 

     // Make sure that a value was entered 
     if (userNameToAddToRole.Trim().Length == 0) 
     { 
          ActionStatus.Text = "You must enter a username in the textbox."; 
          return; 
     } 

     // Make sure that the user exists in the system 
     MembershipUser userInfo = Membership.GetUser(userNameToAddToRole); 
     if (userInfo == null) 
     { 
          ActionStatus.Text = string.Format("The user {0} does not exist in the system.", userNameToAddToRole); 

          return; 
     } 

     // Make sure that the user doesn't already belong to this role 
     if (Roles.IsUserInRole(userNameToAddToRole, selectedRoleName)) 
     { 
          ActionStatus.Text = string.Format("User {0} already is a member of role {1}.", userNameToAddToRole, selectedRoleName); 
          return; 
     } 

     // If we reach here, we need to add the user to the role 
     Roles.AddUserToRole(userNameToAddToRole, 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); }

La maggior parte del codice nel Click gestore eventi esegue vari controlli di convalida. Garantisce che il visitatore abbia fornito un nome utente nel UserNameToAddToRole controllo TextBox, che l'utente esista nel sistema e che non appartenga già al ruolo selezionato. Se uno di questi controlli ha esito negativo, viene visualizzato un messaggio appropriato in ActionStatus e il gestore eventi viene chiuso. Se tutti i controlli vengono superati, l'utente viene aggiunto al ruolo tramite il Roles.AddUserToRole metodo . In seguito, la proprietà textBox Text viene cancellata, gridView viene aggiornata e l'etichetta ActionStatus visualizza un messaggio che indica che l'utente specificato è stato aggiunto correttamente al ruolo selezionato.

Nota

Per assicurarsi che l'utente specificato non appartenga già al ruolo selezionato, viene usato il Roles.IsUserInRole(userName, roleName) metodo , che restituisce un valore booleano che indica se userName è un membro di roleName. Questo metodo verrà usato di nuovo nell'esercitazione successiva quando si esamina l'autorizzazione basata sui ruoli.

Visitare la pagina tramite un browser e selezionare il ruolo Supervisori dall'elenco RoleList a discesa. Provare a immettere un nome utente non valido. Verrà visualizzato un messaggio che spiega che l'utente non esiste nel sistema.

Non è possibile aggiungere un utente non esistente a un ruolo

Figura 9: Non è possibile aggiungere un utente non esistente a un ruolo (fare clic per visualizzare l'immagine a dimensione intera)

Provare ora ad aggiungere un utente valido. Procedere e riaggiungere Tito al ruolo Supervisori.

Tito è ancora una volta un supervisore!

Figura 10: Tito è di nuovo un supervisore! (Fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 3: Aggiornamento incrociato delle interfacce "By User" e "By Role"

La UsersAndRoles.aspx pagina offre due interfacce distinte per la gestione di utenti e ruoli. Attualmente, queste due interfacce agiscono indipendentemente l'una dall'altra in modo che sia possibile che una modifica apportata in un'interfaccia non venga riflessa immediatamente nell'altra. Si supponga, ad esempio, che il visitatore della pagina selezioni il ruolo Supervisori da RoleList DropDownList, che elenca Bruce e Tito come membri. Successivamente, il visitatore seleziona Tito dall'elenco UserList a discesa, che controlla le caselle di controllo Amministratori e supervisori nel UsersRoleList Ripetitore. Se il visitatore deseleziona quindi il ruolo supervisore da Repeater, Tito viene rimosso dal ruolo Supervisori, ma questa modifica non viene riflessa nell'interfaccia "per ruolo". GridView mostrerà ancora Tito come membro del ruolo Supervisori.

Per risolvere questo problema, è necessario aggiornare GridView ogni volta che viene selezionato o deselezionato un ruolo dal UsersRoleList ripetitore. Analogamente, è necessario aggiornare repeater ogni volta che un utente viene rimosso o aggiunto a un ruolo dall'interfaccia "per ruolo".

Il repeater nell'interfaccia "by user" viene aggiornato chiamando il CheckRolesForSelectedUser metodo . L'interfaccia "per ruolo" può essere modificata nel RolesUserList gestore eventi di RowDeleting GridView e nel AddUserToRoleButton gestore eventi del Click pulsante. È quindi necessario chiamare il CheckRolesForSelectedUser metodo da ognuno di questi metodi.

protected void RolesUserList_RowDeleting(object sender, GridViewDeleteEventArgs e) 
{ 
     ... Code removed for brevity ... 

     // Refresh the "by user" interface 
     CheckRolesForSelectedUser(); 
} 

protected void AddUserToRoleButton_Click(object sender, EventArgs e) 
{ 
     ... Code removed for brevity ... 


     // Refresh the "by user" interface 
     CheckRolesForSelectedUser(); 
}

Analogamente, GridView nell'interfaccia "per ruolo" viene aggiornato chiamando il DisplayUsersBelongingToRole metodo e l'interfaccia "per utente" viene modificata tramite il RoleCheckBox_CheckChanged gestore eventi. È quindi necessario chiamare il DisplayUsersBelongingToRole metodo da questo gestore eventi.

protected void RoleCheckBox_CheckChanged(object sender, EventArgs e) 
{ 
     ... Code removed for brevity... 

     // Refresh the "by role" interface 
     DisplayUsersBelongingToRole(); 
}

Con queste modifiche minime al codice, le interfacce "per utente" e "per ruolo" ora aggiornano correttamente. Per verificarlo, visitare la pagina tramite un browser e selezionare Tito e Supervisors rispettivamente da UserList e RoleList DropDownLists. Si noti che quando si deseleziona il ruolo Supervisori per Tito dall'interfaccia "by user", Tito viene rimosso automaticamente dall'interfaccia "per ruolo". L'aggiunta di Tito al ruolo Supervisori dall'interfaccia "per ruolo" controlla automaticamente la casella di controllo Supervisori nell'interfaccia "by user".

Passaggio 4: Personalizzazione di CreateUserWizard per includere un passaggio "Specifica ruoli"

Nell'esercitazione Creazione di account utente è stato illustrato come usare il controllo Web CreateUserWizard per fornire un'interfaccia per la creazione di un nuovo account utente. Il controllo CreateUserWizard può essere usato in uno dei due modi seguenti:

  • Come mezzo per i visitatori di creare il proprio account utente nel sito e
  • Come mezzo per consentire agli amministratori di creare nuovi account

Nel primo caso d'uso, un visitatore accede al sito e compila createUserWizard, immettendo le proprie informazioni per registrarsi nel sito. Nel secondo caso, un amministratore crea un nuovo account per un'altra persona.

Quando un account viene creato da un amministratore per un'altra persona, può essere utile consentire all'amministratore di specificare i ruoli a cui appartiene il nuovo account utente. Nell'esercitazione Sull'archiviazione di informazioni aggiuntive sull'utente è stato illustrato come personalizzare CreateUserWizard aggiungendo altri WizardSteps. Si esamini ora come aggiungere un passaggio aggiuntivo a CreateUserWizard per specificare i ruoli del nuovo utente.

Aprire la CreateUserWizardWithRoles.aspx pagina e aggiungere un controllo CreateUserWizard denominato RegisterUserWithRoles. Impostare la proprietà del ContinueDestinationPageUrl controllo su "~/Default.aspx". Poiché l'idea è che un amministratore usa questo controllo CreateUserWizard per creare nuovi account utente, impostare la proprietà del LoginCreatedUser controllo su False. Questa LoginCreatedUser proprietà specifica se il visitatore è connesso automaticamente come utente appena creato e il valore predefinito è True. L'impostazione viene impostata su False perché quando un amministratore crea un nuovo account che si vuole mantenere connesso come se stesso.

Selezionare quindi "Aggiungi/Rimuovi WizardSteps..." dall'opzione Smart Tag CreateUserWizard e aggiungere un nuovo WizardStepoggetto , impostandone su IDSpecifyRolesStep. Spostare in SpecifyRolesStep WizardStep modo che venga eseguito dopo il passaggio "Iscrizione per il nuovo account", ma prima del passaggio "Completa". Impostare la WizardStepproprietà di su Title "Specifica ruoli", la relativa StepType proprietà su Stepe la relativa AllowReturn proprietà su False.

Screenshot che mostra le proprietà Specifica ruoli selezionate nella finestra Editor raccolta passaggi procedura guidata.

Figura 11: Aggiungere "Specifica ruoli" WizardStep a CreateUserWizard (fare clic per visualizzare l'immagine a dimensione intera)

Dopo questa modifica il markup dichiarativo di CreateUserWizard avrà un aspetto simile al seguente:

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

In "Specifica ruoli" WizardStepaggiungere un controllo CheckBoxList denominato RoleList. Questo checkBoxList elenca i ruoli disponibili, consentendo alla persona che visita la pagina di controllare a quali ruoli appartiene l'utente appena creato.

Per prima cosa è necessario popolare RoleList CheckBoxList con i ruoli nel sistema. In secondo luogo, è necessario aggiungere l'utente creato ai ruoli selezionati quando l'utente passa dal passaggio "Specifica ruoli" al passaggio "Completa". È possibile eseguire la prima attività nel Page_Load gestore eventi. Il codice seguente fa riferimento a RoleList CheckBox nella prima visita alla pagina a livello di codice e associa i ruoli nel sistema.

protected void Page_Load(object sender, EventArgs e) 
{ 
     if (!Page.IsPostBack) 
     { 
          // Reference the SpecifyRolesStep WizardStep 
          WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep; 

          // Reference the RoleList CheckBoxList 
          CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList; 

          // Bind the set of roles to RoleList 
          RoleList.DataSource = Roles.GetAllRoles(); 
          RoleList.DataBind(); 
     } 
}

Il codice precedente dovrebbe avere un aspetto familiare. Nell'esercitazione Archiviazione di informazioni aggiuntive sull'utente sono stati usati due FindControl istruzioni per fare riferimento a un controllo Web dall'interno di un oggetto personalizzatoWizardStep. E il codice che associa i ruoli a CheckBoxList è stato tratto in precedenza in questa esercitazione.

Per eseguire la seconda attività di programmazione, è necessario sapere quando è stato completato il passaggio "Specifica ruoli". Tenere presente che CreateUserWizard ha un ActiveStepChanged evento, che viene generato ogni volta che il visitatore passa da un passaggio a un altro. Qui è possibile determinare se l'utente ha raggiunto il passaggio "Completa" ; in tal caso, è necessario aggiungere l'utente ai ruoli selezionati.

Creare un gestore eventi per l'evento ActiveStepChanged e aggiungere il codice seguente:

protected void RegisterUserWithRoles_ActiveStepChanged(object sender, EventArgs e) 
{ 
     // Have we JUST reached the Complete step? 
     if (RegisterUserWithRoles.ActiveStep.Title == "Complete") 
     { 
          // Reference the SpecifyRolesStep WizardStep 
          WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep; 

          // Reference the RoleList CheckBoxList 
          CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList; 

          // Add the checked roles to the just-added user 
          foreach (ListItem li in RoleList.Items) 

          { 
               if (li.Selected) 
                    Roles.AddUserToRole(RegisterUserWithRoles.UserName, li.Text); 
          } 
     } 
}

Se l'utente ha appena raggiunto il passaggio "Completed", il gestore eventi enumera gli elementi di RoleList CheckBoxList e l'utente appena creato viene assegnato ai ruoli selezionati.

Visitare questa pagina tramite un browser. Il primo passaggio in CreateUserWizard è il passaggio standard "Iscrizione per il nuovo account", che richiede il nome utente, la password, la posta elettronica e altre informazioni sulla chiave del nuovo utente. Immettere le informazioni per creare un nuovo utente denominato Wanda.

Creare un nuovo utente denominato Wanda

Figura 12: Creare un nuovo utente denominato Wanda (fare clic per visualizzare l'immagine a dimensione intera)

Fare clic sul pulsante "Crea utente". CreateUserWizard chiama internamente il Membership.CreateUser metodo , crea il nuovo account utente e quindi passa al passaggio successivo" "Specifica ruoli". Di seguito sono elencati i ruoli di sistema. Selezionare la casella di controllo Supervisori e fare clic su Avanti.

Rendere Wanda un membro del ruolo supervisori

Figura 13: Impostare Wanda come membro del ruolo supervisori (fare clic per visualizzare l'immagine a dimensione intera)

Facendo clic su Avanti viene generato un postback e l'oggetto viene ActiveStep aggiornato al passaggio "Completa". ActiveStepChanged Nel gestore eventi l'account utente creato di recente viene assegnato al ruolo Supervisors. Per verificarlo, tornare alla UsersAndRoles.aspx pagina e selezionare Supervisori dall'elenco RoleList a discesa. Come illustrato nella figura 14, i supervisori sono ora costituiti da tre utenti: Bruce, Tito e Wanda.

Bruce, Tito e Wanda sono tutti supervisori

Figura 14: Bruce, Tito e Wanda sono Tutti i supervisori (fare clic per visualizzare l'immagine a dimensione intera)

Riepilogo

Il framework Ruoli offre metodi per recuperare informazioni sui ruoli e sui metodi di un determinato utente per determinare quali utenti appartengono a un ruolo specificato. Esistono inoltre diversi metodi per aggiungere e rimuovere uno o più utenti a uno o più ruoli. In questa esercitazione sono stati illustrati solo due di questi metodi: AddUserToRole e RemoveUserFromRole. Sono disponibili varianti aggiuntive progettate per aggiungere più utenti a un singolo ruolo e per assegnare più ruoli a un singolo utente.

Questa esercitazione includeva anche un'analisi dell'estensione del controllo CreateUserWizard per includere un WizardStep oggetto per specificare i ruoli dell'utente appena creato. Questo passaggio potrebbe aiutare un amministratore a semplificare il processo di creazione di account utente per nuovi utenti.

A questo punto è stato illustrato come creare ed eliminare ruoli e come aggiungere e rimuovere utenti dai ruoli. Tuttavia, è ancora necessario esaminare l'applicazione dell'autorizzazione basata sui ruoli. Nell'esercitazione seguente si esaminerà la definizione delle regole di autorizzazione degli URL in base al ruolo, nonché come limitare le funzionalità a livello di pagina in base ai ruoli utente attualmente connessi.

Buon programmatori!

Altre informazioni

Per altre informazioni sugli argomenti descritti in questa esercitazione, vedere le risorse seguenti:

Informazioni sull'autore

Scott Mitchell, autore di più libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, lavora con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Scott può essere raggiunto all'indirizzo mitchell@4guysfromrolla.com o tramite il suo blog all'indirizzo http://ScottOnWriting.NET.

Grazie speciale...

Questa serie di esercitazioni è stata esaminata da molti revisori utili. Il revisore principale di questa esercitazione era Teresa Murphy. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com