ユーザーにロールを割り当てる (C#)

作成者: Scott Mitchell

注意

この記事が作成されて以来、ASP.NET メンバーシップ プロバイダーは 、ASP.NET ID に置き換えられました。 この記事の執筆時点で取り上げられたメンバーシップ プロバイダーではなく 、ASP.NET ID プラットフォームを使用するようにアプリを更新することを強くお勧めします。 ASP.NET ID には、ASP.NET メンバーシップ システムに比して、次のような多くの利点があります。

  • パフォーマンスの向上
  • 拡張性とテスト容易性の向上
  • OAuth、OpenID Connect、および 2 要素認証のサポート
  • クレームベースの ID のサポート
  • ASP.Net Core との相互運用性の向上

コードのダウンロード または PDF のダウンロード

このチュートリアルでは、ユーザーがどのロールに属するかの管理を支援する 2 つの ASP.NET ページを作成します。 最初のページには、特定のロールに属しているユーザー、特定のユーザーが属しているロール、特定のロールに対して特定のユーザーを割り当てたり削除したりする機能を確認するための機能が含まれます。 2 番目のページでは、CreateUserWizard コントロールを拡張して、新しく作成されたユーザーが属するロールを指定する手順を含めます。 これは、管理者が新しいユーザー アカウントを作成できるシナリオで役立ちます。

はじめに

前の チュートリアル では、Roles フレームワークと SqlRoleProviderを調べました。クラスを使用してロールを Roles 作成、取得、削除する方法を確認しました。 ロールの作成と削除に加えて、ロールに対するユーザーの割り当てまたは削除が可能である必要があります。 残念ながら、ASP.NET には、どのユーザーがどのロールに属しているのかを管理するための Web コントロールは付属していません。 代わりに、これらの関連付けを管理するために独自の ASP.NET ページを作成する必要があります。 良いニュースは、ロールへのユーザーの追加と削除は非常に簡単です。 Rolesクラスには、1 人以上のユーザーを 1 つ以上のロールに追加するためのメソッドが多数含まれています。

このチュートリアルでは、ユーザーがどのロールに属するかの管理を支援する 2 つの ASP.NET ページを作成します。 最初のページには、特定のロールに属しているユーザー、特定のユーザーが属しているロール、特定のロールに対して特定のユーザーを割り当てたり削除したりする機能を確認するための機能が含まれます。 2 番目のページでは、CreateUserWizard コントロールを拡張して、新しく作成されたユーザーが属するロールを指定する手順を含めます。 これは、管理者が新しいユーザー アカウントを作成できるシナリオで役立ちます。

それでは作業を始めましょう。

どのユーザーがどのロールに属しているのかを一覧表示する

このチュートリアルのビジネスの最初の順序は、ユーザーをロールに割り当てることができる Web ページを作成することです。 ユーザーをロールに割り当てる方法に関心を持つ前に、まず、どのユーザーがどのロールに属しているかを判断する方法に集中しましょう。 この情報を表示するには、"ロール別" または "ユーザー別" の 2 つの方法があります。訪問者がロールを選択し、そのロールに属するすべてのユーザーを表示したり ("ロール別" 表示)、訪問者にユーザーの選択を求め、そのユーザーに割り当てられたロール ("ユーザー別" 表示) を表示することもできます。

"ロール別" ビューは、訪問者が特定のロールに属するユーザーのセットを知りたい場合に役立ちます。"ユーザー別" ビューは、訪問者が特定のユーザーのロールを知る必要がある場合に最適です。 ページに "ロール別" インターフェイスと "ユーザー別" インターフェイスの両方を含めてみましょう。

まず、"ユーザー別" インターフェイスの作成から始めます。 このインターフェイスは、ドロップダウン リストとチェックボックスの一覧で構成されます。 ドロップダウン リストには、システム内のユーザーのセットが設定されます。チェック ボックスはロールを列挙します。 ドロップダウン リストからユーザーを選択すると、ユーザーが属しているロールがチェックされます。 ページにアクセスするユーザーは、チェックボックスをチェックまたはオフにして、選択したユーザーを対応するロールに追加または削除できます。

注意

ドロップダウン リストを使用してユーザー アカウントを一覧表示することは、何百ものユーザー アカウントがある可能性がある Web サイトには最適な選択肢ではありません。 ドロップダウン リストは、ユーザーが比較的短いオプションの一覧から 1 つの項目を選択できるように設計されています。 リスト アイテムの数が増えるにつれて、すぐに扱いにくくなります。 多数のユーザー アカウントを持つ可能性のある Web サイトを構築する場合は、ページング可能な GridView やフィルター可能なインターフェイスなどの代替ユーザー インターフェイスを使用することを検討してください。このインターフェイスには、訪問者にレターの選択を求めるメッセージが表示され、ユーザー名が選択した文字で始まるユーザーのみが表示されます。

手順 1: "ユーザー別" ユーザー インターフェイスの構築

ページを UsersAndRoles.aspx 開きます。 ページの上部に、 という名前 ActionStatus の Label Web コントロールを追加し、そのプロパティを Text クリアします。 このラベルを使用して、実行されたアクションに関するフィードバックを提供し、"User Tito has added to the Administrators role"、または "User Jisun has removed from the Supervisors role" などのメッセージを表示します。これらのメッセージを目立たせるために、Label の CssClass プロパティを "Important" に設定します。

<p align="center"> 

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

次に、次の CSS クラス定義をスタイルシートに Styles.css 追加します。

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

この CSS 定義は、大きな赤いフォントを使用してラベルを表示するようにブラウザーに指示します。 図 1 は、Visual Studio Designerによるこの効果を示しています。

ラベルの CssClass プロパティを使用すると、大きな赤いフォントが表示されます

図 1: ラベルの CssClass プロパティの結果が大きい、赤いフォント (フルサイズの画像を表示する をクリックします)

次に、ページに DropDownList を追加し、そのプロパティを IDUserList設定し、そのプロパティを AutoPostBack True に設定します。 この DropDownList を使用して、システム内のすべてのユーザーを一覧表示します。 この DropDownList は、MembershipUser オブジェクトのコレクションにバインドされます。 DropDownList で MembershipUser オブジェクトの UserName プロパティを表示し、リスト アイテムの値として使用する必要があるため、DropDownList の DataTextField プロパティと DataValueField プロパティを "UserName" に設定します。

DropDownList の下に、 という名前 UsersRoleListの Repeater を追加します。 この Repeater では、システム内のすべてのロールが一連のチェックボックスとして一覧表示されます。 次の宣言型マークアップを使用して、Repeater ItemTemplate の を定義します。

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

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

マークアップには ItemTemplate 、 という名前の 1 つの CheckBox Web コントロールが RoleCheckBox含まれています。 CheckBox の AutoPostBack プロパティは True に設定され、 Text プロパティは に Container.DataItemバインドされます。 データバインド構文が単純である Container.DataItem 理由は、Roles フレームワークがロール名の一覧を文字列配列として返し、この文字列配列が Repeater にバインドされるためです。 この構文を使用してデータ Web コントロールにバインドされた配列の内容を表示する理由については、このチュートリアルでは説明していません。 この問題の詳細については、「 Data Web コントロールへのスカラー配列のバインド」を参照してください。

この時点で、"by user" インターフェイスの宣言型マークアップは次のようになります。

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

これで、ユーザー アカウントのセットを DropDownList にバインドし、ロールのセットを Repeater にバインドするコードを記述する準備ができました。 ページの分離コード クラスで、 という名前のメソッドと、 という名前BindUsersToUserListBindRolesListの別のメソッドを追加します。次のコードを使用します。

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

メソッドはBindUsersToUserList、 メソッドを使用してシステム内のすべてのユーザー アカウントをMembership.GetAllUsers取得します。 これにより、インスタンスのMembershipUserCollectionコレクションMembershipUserである オブジェクトが返されます。 その後、このコレクションは DropDownList に UserList バインドされます。 MembershipUserコレクションを構成するインスタンスには、、EmailCreationDateIsOnline、、 などUserName、さまざまなプロパティが含まれています。 DropDownList にプロパティのUserName値を表示するように指示するには、DropDownList DataTextField の プロパティとDataValueFieldプロパティが "UserName" に設定されていることを確認UserListします。

注意

Membership.GetAllUsersメソッドには 2 つのオーバーロードがあります。1 つは入力パラメーターを受け取らず、すべてのユーザーを返し、1 つはページ インデックスとページ サイズの整数値を受け取り、指定されたユーザーのサブセットのみを返します。 ページング可能なユーザー インターフェイス要素に大量のユーザー アカウントが表示されている場合、2 番目のオーバーロードを使用すると、すべてのユーザー アカウントではなく、ユーザー アカウントの正確なサブセットのみが返されるため、ユーザーを効率的にページングできます。

メソッドはBindRolesToList、 クラスの GetAllRoles メソッドRoles呼び出すことから始まります。このメソッドは、システム内のロールを含む文字列配列を返します。 その後、この文字列配列は Repeater にバインドされます。

最後に、ページが最初に読み込まれるときに、これら 2 つのメソッドを呼び出す必要があります。 Page_Load イベント ハンドラーに次のコードを追加します。

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

このコードを配置した状態で、ブラウザーからページにアクセスしてください。画面は図 2 のようになります。 すべてのユーザー アカウントがドロップダウン リストに入力され、その下に各ロールがチェックボックスとして表示されます。 DropDownList と CheckBoxes のプロパティを True に設定 AutoPostBack しているため、選択したユーザーを変更するか、ロールをオンまたはオフにするとポストバックが発生します。 ただし、これらのアクションを処理するコードをまだ記述していないため、アクションは実行されません。 これらのタスクは、次の 2 つのセクションで取り組みます。

ページにユーザーとロールが表示されます

図 2: ページにユーザーとロールが表示されます (クリックするとフルサイズの画像が表示されます)

選択したユーザーが属しているロールの確認

ページが最初に読み込まれるとき、または訪問者がドロップダウン リストから新しいユーザーを選択するたびに、選択したユーザーがそのロールに属している場合にのみ特定のロールチェックボックスがオンになるように、チェックボックスを更新 UsersRoleListする必要があります。 これを実現するには、次のコードを使用して という名前 CheckRolesForSelectedUser のメソッドを作成します。

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

上記のコードは、選択したユーザーが誰であるかを判断することから始まります。 次に、Roles クラスの GetRolesForUser(userName) メソッド を使用して、指定したユーザーのロールのセットを文字列配列として返します。 次に、Repeater の項目が列挙され、各項目の RoleCheckBox CheckBox がプログラムによって参照されます。 CheckBox は、対応するロールが文字列配列内 selectedUsersRoles に含まれている場合にのみチェックされます。

注意

selectedUserRoles.Contains<string>(...)バージョン 2.0 ASP.NET 使用している場合、構文はコンパイルされません。 メソッドは Contains<string>LINQ ライブラリの一部であり、ASP.NET 3.5 の新機能です。 まだバージョン 2.0 ASP.NET 使用している場合は、代わりに メソッドをArray.IndexOf<string>使用します。

メソッドは CheckRolesForSelectedUser 、ページが最初に読み込まれるときと、DropDownList の選択したインデックスが変更されるたびに UserList 、2 つの場合に呼び出す必要があります。 そのため、イベント ハンドラーからこのメソッドを Page_Load 呼び出します (および の BindUsersToUserList 呼び出し BindRolesToListの後)。 また、DropDownList SelectedIndexChanged のイベントのイベント ハンドラーを作成し、そこからこのメソッドを呼び出します。

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

このコードを配置すると、ブラウザーを使用してページをテストできます。 ただし、ページには UsersAndRoles.aspx 現在、ユーザーをロールに割り当てる機能がないため、ロールを持つユーザーはいません。 ユーザーをロールに割り当てるためのインターフェイスをすぐに作成するので、このコードが機能することを私の言葉で確認し、後でそうすることを確認するか、この機能を今すぐテストするためにレコードをテーブルに aspnet_UsersInRoles 挿入してユーザーをロールに手動で追加できます。

ロールへのユーザーの割り当てと削除

訪問者が Repeater で UsersRoleList CheckBox をチェックまたはオフにした場合は、選択したユーザーを対応するロールに追加または削除する必要があります。 CheckBox の AutoPostBack プロパティは現在 True に設定されています。これにより、Repeater の CheckBox がオンまたはオフの場合は、いつでもポストバックが発生します。 要するに、CheckBox CheckChanged のイベントのイベント ハンドラーを作成する必要があります。 CheckBox は Repeater コントロール内にあるため、イベント ハンドラーのプラミングを手動で追加する必要があります。 まず、次のように、分離コード クラスにメソッドとしてイベント ハンドラーを protected 追加します。

protected void RoleCheckBox_CheckChanged(object sender, EventArgs e) 
{ 

}

に戻り、このイベント ハンドラーのコードをしばらく書き込みます。 しかし、まず、イベント処理のプラミングを完了しましょう。 Repeater ItemTemplateの 内の CheckBox から、 を追加します OnCheckedChanged="RoleCheckBox_CheckChanged"。 この構文では、イベント ハンドラーを RoleCheckBox_CheckChangedCheckedChanged イベントにRoleCheckBox結び付けます。

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

最後のタスクは、イベント ハンドラーを RoleCheckBox_CheckChanged 完了することです。 最初に、イベントを発生させた CheckBox コントロールを参照する必要があります。この CheckBox インスタンスは、その プロパティと Checked プロパティを介してチェックまたはオフにされたロールをText示します。 この情報を選択したユーザーの UserName と共に使用して、クラスAddUserToRoleまたは メソッドを使用してロールに対してユーザーをRoles追加またはRemoveUserFromRole削除します。

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

     } 
}

上記のコードは、イベントを発生させた CheckBox をプログラムで参照することから始まります。これは、入力パラメーターを sender 介して使用できます。 CheckBox をオンにすると、選択したユーザーが指定したロールに追加され、それ以外の場合はロールから削除されます。 いずれの場合も、[ラベル] ActionStatus には、実行したアクションを要約したメッセージが表示されます。

ブラウザーを使用してこのページをテストしてください。 [ユーザー Tito] を選択し、[管理者] ロールと [Supervisors] ロールの両方に Tito を追加します。

Tito が管理者および監督者ロールに追加されました

図 3: Tito が管理者と監督者の役割に追加されました (フルサイズの画像を表示する をクリックします)

次に、ドロップダウン リストからユーザー Bruce を選択します。 ポストバックがあり、Repeater の CheckBox は を CheckRolesForSelectedUser介して更新されます。 Bruce はまだロールに属していないため、2 つのチェック ボックスはオフになっています。 次に、Supervisors ロールに Bruce を追加します。

Bruce が Supervisors ロールに追加されました

図 4: Bruce が Supervisors ロールに追加されました (フルサイズの画像を表示する をクリックします)

メソッドの CheckRolesForSelectedUser 機能をさらに確認するには、Tito または Bruce 以外のユーザーを選択します。 チェック ボックスが自動的にオフになっていることに注意してください。これは、どのロールにも属していない点に注意してください。 Tito に戻ります。 [管理者] と [スーパーバイザー] の両方のチェック ボックスをオンにする必要があります。

手順 2: "ロール別" ユーザー インターフェイスの構築

この時点で、"by users" インターフェイスを完了し、"ロール別" インターフェイスへの取り組みを開始する準備ができました。 "ロール別" インターフェイスは、ドロップダウン リストからロールを選択するようにユーザーに求め、そのロールに属するユーザーのセットを GridView に表示します。

別の DropDownList コントロールをページに UsersAndRoles.aspx 追加します。 この 1 つを Repeater コントロールの下に配置し、 という名前を付け RoleList、そのプロパティを AutoPostBack True に設定します。 その下に GridView を追加し、 という名前を付けます RolesUserList。 この GridView には、選択したロールに属しているユーザーが一覧表示されます。 GridView の AutoGenerateColumns プロパティを False に設定し、TemplateField をグリッドの Columns コレクションに追加し、その HeaderText プロパティを "Users" に設定します。 という名前UserNameLabelItemTemplate Label の プロパティに databinding 式Container.DataItemTextの値を表示するように TemplateField を定義します。

GridView を追加して構成した後、"by role" インターフェイスの宣言型マークアップは次のようになります。

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

システム内のロールのセットを RoleList DropDownList に設定する必要があります。 これを実現するには、 メソッドを更新して BindRolesToList 、 メソッドによって返される文字列配列を Roles.GetAllRolesRolesList DropDownList (および Repeater) に UsersRoleList バインドします。

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

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

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

メソッドの最後の BindRolesToList 2 行が追加され、ロールのセットが DropDownList コントロールに RoleList バインドされました。 図 5 は、ブラウザーを使用して表示したときの最終的な結果を示しています。ドロップダウン リストには、システムの役割が入力されています。

ロールは RoleList DropDownList に表示されます

図 5: ロールが DropDownList に RoleList 表示される (フルサイズの画像を表示するをクリックします)

選択したロールに属するユーザーの表示

ページが最初に読み込まれるとき、または DropDownList から RoleList 新しいロールが選択されたときに、そのロールに属するユーザーの一覧を GridView に表示する必要があります。 次のコードを使用して、 という名前 DisplayUsersBelongingToRole のメソッドを作成します。

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

このメソッドは、最初に DropDownList から選択したロールを RoleList 取得します。 次に、 メソッドをRoles.GetUsersInRole(roleName)使用して、そのロールに属するユーザーの UserNames の文字列配列を取得します。 その後、この配列は GridView に RolesUserList バインドされます。

このメソッドは、ページが最初に読み込まれるときと、DropDownList で選択したロールが変更されたときの 2 つの状況で呼び出す RoleList 必要があります。 そのため、 の呼び出し後に Page_Load このメソッドが呼び出されるように、イベント ハンドラーを更新します CheckRolesForSelectedUser。 次に、 の イベントのイベント ハンドラーをRoleListSelectedIndexChanged作成し、そこからこのメソッドも呼び出します。

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

このコードを配置すると、GridView には、 RolesUserList 選択したロールに属しているユーザーが表示されます。 図 6 に示すように、Supervisors ロールは、Bruce と Tito の 2 つのメンバーで構成されています。

GridView には、選択したロールに属しているユーザーが一覧表示されます

図 6: GridView には、選択したロールに属しているユーザーが一覧表示されます (フルサイズの画像を表示する をクリックします)

選択したロールからのユーザーの削除

"削除" ボタンの RolesUserList 列が含まれるように GridView を拡張してみましょう。 特定のユーザーの [削除] ボタンをクリックすると、そのロールから削除されます。

まず、GridView に [削除] ボタン フィールドを追加します。 このフィールドを最も左のファイルとして表示し、そのプロパティを DeleteText "Delete" (既定値) から "Remove" に変更します。

[フィールド] ウィンドウに [削除] ボタンを追加する方法を示すスクリーンショット。

図 7: GridView に [削除] ボタンを追加します (フルサイズの画像を表示する場合をクリックします)

[削除] ボタンをクリックするとポストバックが続き、GridView の RowDeleting イベントが発生します。 このイベントのイベント ハンドラーを作成し、選択したロールからユーザーを削除するコードを記述する必要があります。 イベント ハンドラーを作成し、次のコードを追加します。

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

コードは、選択したロール名を決定することから始まります。 次に、"削除" ボタンがクリックされた行からコントロールをプログラムで参照 UserNameLabel して、削除するユーザーの UserName を決定します。 その後、ユーザーは メソッドの呼び出し Roles.RemoveUserFromRole によってロールから削除されます。 RolesUserListその後、GridView が更新され、Label コントロールを介してメッセージがActionStatus表示されます。

注意

[削除] ボタンでは、ロールからユーザーを削除する前に、ユーザーからの確認は必要ありません。 何らかのレベルのユーザー確認を追加するようお勧めします。 アクションを確認する最も簡単な方法の 1 つは、クライアント側の確認ダイアログ ボックスを使用することです。 この手法の詳細については、「 削除時のClient-Side確認の追加」を参照してください。

図 8 は、ユーザー Tito が Supervisors グループから削除された後のページを示しています。

悲しいかな、ティトはもはやスーパーバイザーではない

図 8: アラス、ティトはもはやスーパーバイザーではありません (フルサイズの画像を表示する をクリックします)

選択したロールへの新しいユーザーの追加

選択したロールからユーザーを削除すると共に、このページの訪問者は、選択したロールにユーザーを追加することもできます。 選択したロールにユーザーを追加するための最適なインターフェイスは、使用するユーザー アカウントの数によって異なります。 Web サイトに数十個以下のユーザー アカウントが含まれていることがある場合は、ここで DropDownList を使用できます。 何千ものユーザー アカウントがある場合は、訪問者がアカウントをページングしたり、特定のアカウントを検索したり、他の方法でユーザー アカウントをフィルター処理したりできるようにするユーザー インターフェイスを含めることができます。

このページでは、システム内のユーザー アカウントの数に関係なく動作する非常に単純なインターフェイスを使用しましょう。 つまり、TextBox を使用して、選択したロールに追加するユーザーのユーザー名を入力するように訪問者に求めます。 その名前のユーザーが存在しない場合、またはユーザーが既にロールのメンバーである場合は、[ラベル] に ActionStatus メッセージが表示されます。 ただし、ユーザーが存在し、ロールのメンバーでない場合は、そのユーザーをロールに追加し、グリッドを更新します。

GridView の下に TextBox とボタンを追加します。 TextBox ID の を にUserNameToAddToRole設定し、Button ID の プロパティと プロパティをそれぞれ AddUserToRoleButton に設定しText、それぞれ "ロールにユーザーを追加" に設定します。

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

次に、 の Click イベント ハンドラーを AddUserToRoleButton 作成し、次のコードを追加します。

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

イベント ハンドラーのコードの大部分は、 Click さまざまな検証チェックを実行します。 これにより、訪問者が TextBox にユーザー名を UserNameToAddToRole 指定し、ユーザーがシステムに存在し、選択したロールにまだ属していないことを確認します。 これらのチェックのいずれかが失敗した場合は、 に ActionStatus 適切なメッセージが表示され、イベント ハンドラーが終了します。 すべてのチェックに合格すると、 メソッドを使用してユーザーがロールに Roles.AddUserToRole 追加されます。 その後、TextBox の Text プロパティがクリアされ、GridView が更新され ActionStatus 、指定したユーザーが選択したロールに正常に追加されたことを示すメッセージが Label に表示されます。

注意

指定したユーザーが選択したロールにまだ属していないことを確認するために、 メソッドをRoles.IsUserInRole(userName, roleName)使用します。このメソッドは、userNameroleName のメンバーであるかどうかを示すブール値を返します。 ロールベースの承認を確認するときは、次の チュートリアル でこの方法をもう一度使用します。

ブラウザーからページにアクセスし、DropDownList から Supervisors ロールを RoleList 選択します。 無効なユーザー名を入力してみてください。ユーザーがシステムに存在しないことを説明するメッセージが表示されます。

存在しないユーザーをロールに追加することはできません

図 9: 存在しないユーザーをロールに追加できません (フルサイズの画像を表示する場合をクリックします)

次に、有効なユーザーを追加してみてください。 先に進み、Tito を Supervisors ロールに再追加します。

ティトは再びスーパーバイザーです!

図 10: ティトはもう一度スーパーバイザーです! (クリックするとフルサイズの画像が表示されます)

手順 3: "By User" インターフェイスと "By Role" インターフェイスをクロス更新する

この UsersAndRoles.aspx ページには、ユーザーとロールを管理するための 2 つの異なるインターフェイスが用意されています。 現在、これら 2 つのインターフェイスは互いに独立して動作するため、一方のインターフェイスで行われた変更が他のインターフェイスにすぐに反映されない可能性があります。 たとえば、ページの訪問者が DropDownList から Supervisors ロールを RoleList 選択するとします。このロールには、Bruce と Tito がメンバーとして一覧表示されます。 次に、訪問者は DropDownList から UserList Tito を選択し、Repeater の [Administrators and Supervisors]\(管理者とスーパーバイザー\) チェックボックスを UsersRoleList オンにします。 その後、訪問者が Repeater から Supervisor ロールをオフにした場合、Tito は Supervisors ロールから削除されますが、この変更は "by role" インターフェイスには反映されません。 GridView は引き続き Tito を Supervisors ロールのメンバーとして表示します。

これを修正するには、ロールが Repeater でオンまたはオフになっている場合は常に GridView を更新する UsersRoleList 必要があります。 同様に、ユーザーが "by role" インターフェイスからロールに削除または追加されるたびに、Repeater を更新する必要があります。

"by user" インターフェイスの Repeater は、 メソッドを CheckRolesForSelectedUser 呼び出すことによって更新されます。 "ロール別" インターフェイスは、GridView RowDeletingRolesUserListイベント ハンドラーと Button Click のイベント ハンドラーでAddUserToRoleButton変更できます。 したがって、これらの各メソッドから メソッドを CheckRolesForSelectedUser 呼び出す必要があります。

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

同様に、"by role" インターフェイスの GridView は メソッドを DisplayUsersBelongingToRole 呼び出すことによって更新され、"by user" インターフェイスはイベント ハンドラーを RoleCheckBox_CheckChanged 介して変更されます。 そのため、このイベント ハンドラーから メソッドを DisplayUsersBelongingToRole 呼び出す必要があります。

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

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

これらのマイナー コードの変更により、"by user" インターフェイスと "by role" インターフェイスが正しくクロス更新されるようになりました。 これを確認するには、ブラウザーからページにアクセスし、 と DropDownLists から UserList Tito と RoleList Supervisors をそれぞれ選択します。 "by user" インターフェイスの Repeater から Tito の Supervisors ロールをオフにすると、Tito は "by role" インターフェイスの GridView から自動的に削除されることに注意してください。 "by role" インターフェイスから Supervisors ロールに Tito を追加すると、"by user" インターフェイスの Supervisors チェックボックスが自動的に再チェックされます。

手順 4: CreateUserWizard をカスタマイズして "ロールの指定" ステップを含める

ユーザー アカウント作成チュートリアルでは、CreateUserWizard Web コントロールを使用して、新しいユーザー アカウントを作成するためのインターフェイスを提供する方法について説明しました。 CreateUserWizard コントロールは、次の 2 つの方法のいずれかで使用できます。

  • 訪問者がサイトで独自のユーザー アカウントを作成するための手段として、
  • 管理者が新しいアカウントを作成する手段として

最初のユース ケースでは、訪問者がサイトに来て CreateUserWizard に入力し、サイトに登録するために情報を入力します。 2 番目のケースでは、管理者が別のユーザーの新しいアカウントを作成します。

管理者が他のユーザーのアカウントを作成する場合は、管理者が新しいユーザー アカウントが属するロールを指定できるようにすると便利な場合があります。 追加のユーザー情報格納に関するチュートリアルでは、 を追加WizardStepsして CreateUserWizard をカスタマイズする方法を確認しました。 新しいユーザーのロールを指定するために、CreateUserWizard に追加の手順を追加する方法を見てみましょう。

ページを CreateUserWizardWithRoles.aspx 開き、 という名前 RegisterUserWithRolesの CreateUserWizard コントロールを追加します。 コントロールの ContinueDestinationPageUrl プロパティを "~/Default.aspx" に設定します。 ここでの考え方は、管理者がこの CreateUserWizard コントロールを使用して新しいユーザー アカウントを作成するため、コントロールの LoginCreatedUser プロパティを False に設定します。 このプロパティは LoginCreatedUser 、作成したばかりのユーザーとして訪問者が自動的にログオンするかどうかを指定し、既定値は True です。 管理者が新しいアカウントを作成するときに、自分としてサインインしたままにしておく必要があるため、False に設定します。

次に、[追加/削除 WizardSteps] を選択します。オプションを選択し、新しい WizardStepを追加し、 を ID に設定します SpecifyRolesStepSpecifyRolesStep WizardStepを移動して、"新しいアカウントにサインアップする" ステップの後、"完了" ステップの前に移動します。 の プロパティを WizardStep"ロールの Title 指定" に設定し、その StepType プロパティを に Step設定し、その AllowReturn プロパティを False に設定します。

[ウィザード ステップ コレクション エディター] ウィンドウで選択した [ロールの指定] プロパティを示すスクリーンショット。

図 11: CreateUserWizard に "ロールの指定" WizardStep を追加します (フルサイズの画像を表示するには、ここをクリックします)

この変更後、CreateUserWizard の宣言型マークアップは次のようになります。

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

[ロール WizardStepの指定] で、 という名前 RoleListの CheckBoxList を追加します。 この CheckBoxList には、使用可能なロールが一覧表示され、ページにアクセスするユーザーが、新しく作成されたユーザーが属するロールをチェックできるようになります。

2 つのコーディング タスクが残されています。最初に、CheckBoxList にシステム内のロールを設定 RoleList する必要があります。2 つ目は、ユーザーが [ロールの指定] ステップから [完了] ステップに移動したときに、選択したロールに作成されたユーザーを追加する必要があります。 イベント ハンドラーで最初のタスクを Page_Load 実行できます。 次のコードは、ページへの最初の RoleList アクセス時に CheckBox をプログラムで参照し、システム内のロールをそのページにバインドします。

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

上記のコードは使い慣れているはずです。 追加のユーザー情報格納に関するチュートリアルでは、カスタム 内から Web コントロールを参照するために 2 つのFindControlステートメントを使用しましたWizardStep。 また、ロールを CheckBoxList にバインドするコードは、このチュートリアルの前半から取得しました。

2 番目のプログラミング タスクを実行するには、"ロールの指定" ステップがいつ完了したかを把握する必要があります。 CreateUserWizard には ActiveStepChanged イベントがあり、訪問者が 1 つのステップから別のステップに移動するたびに発生することを思い出してください。 ここでは、ユーザーが "完了" ステップに達したかどうかを確認できます。その場合は、選択したロールにユーザーを追加する必要があります。

イベントのイベント ハンドラーを ActiveStepChanged 作成し、次のコードを追加します。

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

ユーザーが "完了" ステップに到達したばかりの場合、イベント ハンドラーは CheckBoxList の項目を RoleList 列挙し、作成したユーザーが選択したロールに割り当てられます。

ブラウザーからこのページにアクセスします。 CreateUserWizard の最初の手順は、新しいユーザーのユーザー名、パスワード、電子メール、およびその他のキー情報の入力を求める標準の "新しいアカウントへのサインアップ" ステップです。 情報を入力して、Wanda という名前の新しいユーザーを作成します。

Wanda という名前の新しいユーザーを作成する

図 12: Wanda という名前の新しいユーザーを作成する (フルサイズの画像を表示する をクリックします)

[ユーザーの作成] ボタンをクリックします。 CreateUserWizard は内部的に メソッドを Membership.CreateUser 呼び出し、新しいユーザー アカウントを作成し、次の手順である "ロールの指定" に進みます。ここでは、システムロールが一覧表示されます。 [Supervisors]\(スーパーバイザー\) チェックボックスをオンにし、[Next]\(次へ\) をクリックします。

Wanda をスーパーバイザー ロールのメンバーにする

図 13: Wanda をスーパーバイザー ロールのメンバーにする (フルサイズの画像を表示する をクリックします)

[次へ] をクリックするとポストバックが発生し、 が ActiveStep "完了" ステップに更新されます。 ActiveStepChangedイベント ハンドラーでは、最近作成したユーザー アカウントが Supervisors ロールに割り当てられます。 これを確認するには、ページに UsersAndRoles.aspx 戻り、DropDownList から Supervisors を RoleList 選択します。 図 14 に示すように、スーパーバイザーは現在、Bruce、Tito、Wanda の 3 人のユーザーで構成されています。

Bruce、Tito、Wanda はすべてスーパーバイザーです

図 14: Bruce、Tito、Wanda はすべてスーパーバイザーです (フルサイズの画像を表示する をクリックします)

まとめ

Roles フレームワークには、特定のユーザーのロールに関する情報を取得するためのメソッドと、指定したロールに属しているユーザーを決定するためのメソッドが用意されています。 さらに、1 つ以上のユーザーを 1 つ以上のロールに追加および削除する方法がいくつかあります。 このチュートリアルでは、 と RemoveUserFromRoleの 2 つの方法に焦点をAddUserToRole当てています。 1 つのロールに複数のユーザーを追加し、1 人のユーザーに複数のロールを割り当てるために設計された追加のバリエーションがあります。

このチュートリアルでは、CreateUserWizard コントロールを拡張して、 を含 WizardStep め、新しく作成されたユーザーのロールを指定する方法についても説明しました。 このような手順は、管理者が新しいユーザーのユーザー アカウントを作成するプロセスを効率化するのに役立ちます。

この時点で、ロールを作成および削除する方法と、ロールに対してユーザーを追加および削除する方法について説明しました。 ただし、ロールベースの承認の適用はまだ見ていません。 次の チュートリアル では、ロールごとに URL 承認規則を定義する方法と、現在ログインしているユーザーのロールに基づいてページ レベルの機能を制限する方法について説明します。

プログラミングに満足!

もっと読む

このチュートリアルで説明するトピックの詳細については、次のリソースを参照してください。

著者について

複数の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・自分自身 ASP.NET 24時間で2.0です。 Scott は、 または mitchell@4guysfromrolla.com のブログを http://ScottOnWriting.NET介してアクセスできます。

特別な感謝...

このチュートリアル シリーズは、多くの役立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、テレサ マーフィーでした。 今後の MSDN 記事の確認に関心がありますか? もしそうなら、私に行を落としてください mitchell@4GuysFromRolla.com