.NET TIPS

[ASP.NET]メンバシップAPIでユーザー情報の編集を行うには?[2.0、3.0、3.5、C#、VB]

山田 祥寛
2008/07/03

 「TIPS:[ASP.NET]セキュリティ・コントロールでログイン機能を作成するには?」で紹介したように、ASP.NET 2.0以降ではログイン・コントロール(セキュリティ・コントロール)が導入され、ログイン機能やパスワード問い合わせ/変更、ユーザー新規作成など、ユーザー管理にかかわる諸機能をほぼコーディングレスで実現できるようになった。もっとも、実際にアプリケーションを構築するうえでは、標準的なログイン・コントロールだけでは賄えないような機能を実装したいという局面も多々発生するはずだ。

 しかし、心配することなかれ、ASP.NETではメンバシップ情報にアクセスするための専用の「メンバシップAPI」を提供している。メンバシップAPIを利用することで、メンバシップ情報を格納したデータソースをほとんど意識することなく、直感的に各種情報へアクセスすることが可能になる。

 本稿では、このメンバシップAPIを利用して、既存のユーザー情報/プロファイル情報を確認/編集するためのページを作成する。

グリッド表からユーザー情報を編集/削除

 それではさっそく、具体的な手順を見ていくことにしよう。なお、本稿のサンプルを実行するには、前述のTIPSを参考にいくつかのユーザー情報を作成しておく必要がある。

1. データアクセス・コンポーネントを定義する

 まずは、メンバシップ情報にアクセスし、ユーザー関連の情報を取得/更新/削除するためのデータアクセス・コンポーネントを作成する必要がある。なお、作成したデータアクセス・コンポーネント(.vb/.csファイル)は、アプリケーション・ルート直下の「App_Code」フォルダに配置する必要がある(*1)。

*1 「App_Code」フォルダは.vb/.csファイルなどのコードを配置するためのアプリケーション・フォルダで、本フォルダの内容は実行時に動的にコンパイルされる。

 具体的には次のコードのようなデータアクセス・コンポーネントを作成する。

using System;
using System.Data;
using System.Collections.Generic;
using System.Configuration;
using System.Security.Principal;
using System.Web;
using System.Web.Profile;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public class User {
  // 取得したユーザー情報を格納するための各種プロパティを定義。
  // 具体的には、Name(ユーザ名)、KanjiName(ユーザ名漢字)、
  // Email(E-Mailアドレス)、
  // IsLockedOut(ロックアウトされているか)、
  // IsAdmin(管理者権限を持っているか)
  // といったプロパティを持つものとする
  private String _name;
  private String _kanjiName;
  private String _email;
  private Boolean _isLockedOut;
  private Boolean _isAdmin;

  public String Name {
    get { return this._name; }
    set { this._name = value; }
  }
  public String KanjiName {
    get { return this._kanjiName; }
    set { this._kanjiName = value; }
  }
  public String Email {
    get { return this._email; }
    set { this._email = value; }
  }
  public Boolean IsLockedOut {
    get { return this._isLockedOut; }
    set { this._isLockedOut = value; }
  }
  public Boolean IsAdmin {
    get { return this._isAdmin; }
    set { this._isAdmin = value; }
  }

  // 定義済みの全ユーザー情報を取得するためのSELECTメソッド
  public List<User> GetAllInfos() {
    List<User> result = new List<User>();

    // 取得したユーザー情報をUserオブジェクトに詰め替え、
    // 順にListオブジェクトに追加
    foreach (MembershipUser usr in Membership.GetAllUsers()) {
      User data = new User();
      data.Name = usr.UserName;
      data.KanjiName = (String)ProfileBase.Create(
        usr.UserName).GetPropertyValue("MyName");
      data.Email = usr.Email;
      data.IsLockedOut = usr.IsLockedOut;
      data.IsAdmin = Roles.IsUserInRole(usr.UserName, "Admin");
      result.Add(data);
    }
    // 出来上がったUserオブジェクトのリストを戻り値として返す
    return result;
  }

  // 指定されたユーザーの情報を更新するためのUPDATEメソッド
  public void UpdateInfo(User usr) {

    // 更新対象のユーザー(MembershipUserオブジェクト)を取得
    // Emailプロパティを書き換え、更新
    MembershipUser current = Membership.GetUser(usr.Name);
    current.Email = usr.Email;
    Membership.UpdateUser(current);

    // ロックアウトの更新を実行。
    // 更新対象のユーザーがロックアウト状態にあり、かつ、渡された
    // 更新情報(Userオブジェクト)がロックアウト状態にない場合、
    // ロックアウトを解除(ロックアウト設定はできないものとする)
    if (current.IsLockedOut && !usr.IsLockedOut) {
      current.UnlockUser();
    }

    // ロール情報の更新を実行。更新対象のユーザーがAdmin権限を
    // 持っておらず、かつ、渡された更新情報(Userオブジェクト)が
    // Admin権限を持っている場合、
    // Admin権限の追加処理を、逆の場合はAdmin権限の削除処理を行う
    Boolean admin = Roles.IsUserInRole(usr.Name, "Admin");
    if (!admin && usr.IsAdmin) {
      Roles.AddUserToRole(usr.Name, "Admin");
    }
    if (admin && !usr.IsAdmin) {
      Roles.RemoveUserFromRole(usr.Name, "Admin");
    }

    // プロファイルMyNameを設定
    ProfileBase prof = ProfileBase.Create(usr.Name);
    prof.SetPropertyValue("MyName", usr.KanjiName);
    prof.Save();
  }

  // 指定されたユーザーの情報を削除するためのDELETEメソッド
  public void DeleteInfo(User usr) {
    Membership.DeleteUser(usr.Name);
  }
}
Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Imports System.Security.Principal

Public Class User
  ' 取得したユーザー情報を格納するための各種プロパティを定義。
  ' 具体的には、Name(ユーザ名)、KanjiName(ユーザ名漢字)、
  ' Email(E-Mailアドレス)、
  ' IsLockedOut(ロックアウトされているか)、
  ' IsAdmin(管理者権限を持っているか)
  ' といったプロパティを持つものとする
  Private _name As String
  Private _kanjiName As String
  Private _email As String
  Private _isLockedOut As Boolean
  Private _isAdmin As Boolean

  Public Property Name() As String
    Get
      Return Me._name
    End Get
    Set(ByVal value As String)
      Me._name = value
    End Set
  End Property
  Public Property KanjiName() As String
    Get
      Return Me._kanjiName
    End Get
    Set(ByVal value As String)
      Me._kanjiName = value
    End Set
  End Property
  Public Property Email() As String
    Get
      Return Me._email
    End Get
    Set(ByVal value As String)
      Me._email = value
    End Set
  End Property
  Public Property IsLockedOut() As Boolean
    Get
      Return Me._isLockedOut
    End Get
    Set(ByVal value As Boolean)
      Me._isLockedOut = value
    End Set
  End Property
  Public Property IsAdmin() As Boolean
    Get
      Return Me._isAdmin
    End Get
    Set(ByVal value As Boolean)
      Me._isAdmin = value
    End Set
  End Property

  ' 定義済みの全ユーザ情報を取得するためのSELECTメソッド
  Public Function GetAllInfos() As List(Of User)
    Dim result As New List(Of User)

    ' 取得したユーザー情報をUserオブジェクトに詰め替え、
    ' 順にListオブジェクトに追加
    For Each usr As MembershipUser In Membership.GetAllUsers()
      Dim data As New User()
      data.Name = usr.UserName
      data.KanjiName = ProfileBase.Create( _
        usr.UserName).GetPropertyValue("MyName")
      data.Email = usr.Email
      data.IsLockedOut = usr.IsLockedOut
      data.IsAdmin = Roles.IsUserInRole(usr.UserName, "Admin")
      result.Add(data)
    Next

    ' 出来上がったUserオブジェクトのリストを戻り値として返す
    Return result
  End Function

  ' 指定されたユーザーの情報を更新するためのUPDATEメソッド
  Public Sub UpdateInfo(ByVal usr As User)

    ' 更新対象のユーザー(MembershipUserオブジェクト)を取得
    ' Emailプロパティを書き換え、更新
    Dim current As MembershipUser = Membership.GetUser(usr.Name)
    current.Email = usr.Email
    Membership.UpdateUser(current)

    ' ロックアウトの更新を実行。
    ' 更新対象のユーザーがロックアウト状態にあり、かつ、渡された
    '更新情報(Userオブジェクト)がロックアウト状態にない場合、
    ' ロックアウトを解除(ロックアウト設定はできないものとする)
    If current.IsLockedOut And Not usr.IsLockedOut Then
      current.UnlockUser()
    End If

    ' ロール情報の更新を実行。
    ' 更新対象のユーザーがAdmin権限を持っておらず、かつ、渡された
    ' 更新情報(Userオブジェクト)がAdmin権限を持っている場合、
    ' Admin権限の追加処理を、逆の場合はAdmin権限の削除処理を行う
    Dim admin As Boolean = Roles.IsUserInRole(usr.Name, "Admin")
    If Not admin And usr.IsAdmin Then
      Roles.AddUserToRole(usr.Name, "Admin")
    End If
    If admin And Not usr.IsAdmin Then
      Roles.RemoveUserFromRole(usr.Name, "Admin")
    End If

    ' プロファイルMyNameを設定
    Dim prof As ProfileBase = ProfileBase.Create(usr.Name)
    prof.SetPropertyValue("MyName", usr.KanjiName)
    prof.Save()
  End Sub

  ' 指定されたユーザーの情報を削除するためのDELETEメソッド
  Public Sub DeleteInfo(ByVal usr As User)
    Membership.DeleteUser(usr.Name)
  End Sub
End Class
ユーザー情報を取得/更新/削除するためのデータアクセス・コンポーネント(上:C#版User.cs、下:Visual Basic版User.vb)

 ここでは、あとからObjectDataSourceコントロールにひも付けるためのSELECT/UPDATE/DELETEメソッドを定義しておくものとする(ObjectDataSourceコントロールに関する詳細は、「データソース・コントロールでいってみよう(前編)」も参照)。コードの大まかな流れはリスト内のコメントも参照いただくとして、ここではメンバシップAPIによるユーザー情報操作の手順に注目してみよう。

(1)ユーザー情報を取得/更新する

 まず、ユーザー情報を取得するのはMembershipクラス(System.Web.Security名前空間)のGetAllUsers/GetUserメソッドだ。すべてのユーザー情報を取得したい場合にはGetAllUsersメソッドを、指定されたユーザー名に対応する情報を取得したい場合にはGetUserメソッドを使用すればよい。これらのメソッドはそれぞれ、MembershipUserオブジェクトのリスト、単一のMembershipUserオブジェクトを返す。

 MembershipUserクラスで利用可能な主なプロパティは、以下のとおり。

プロパティ 概要
CreationDate 作成日時
Email 電子メール・アドレス
IsLockedOut ロックアウト状態にあるか
IsOnline オンライン中であるか
LastActivityDate 最後にアクセスした日時
LastLoginDate 最後に認証された日時
LastPasswordChangedDate 最後にパスワードが変更された日時
PasswordQuestion 秘密の質問
UserName ユーザー名
MembershipUserクラス(System.Web.Security名前空間)で利用可能な主なプロパティ

 User.vb/User.csのGetAllInfosメソッドでは、このMembershipUserオブジェクトから取得したユーザー名/ロック状態/電子メールなどの情報をUserオブジェクトにセットし直しているというわけだ。

 ユーザー情報を更新する場合には、MembershipUserオブジェクトの該当するプロパティに情報をセットしたうえで、Membership.UpdateUserメソッドを呼び出せばよい(プロパティに値をセットしただけでは更新は反映されないので注意すること)。

 ただし、IsLockedOutプロパティだけは読み取り専用で直接には更新できないので要注意。更新前のユーザー情報がロックアウト状態にあり(IsLockedOutプロパティがtrue)、かつ、更新後のユーザー情報がfalseである場合に、MembershipUser.UnlockUserメソッドを呼び出している。ちなみに、ユーザーをロックアウト状態にするLockUserのようなメソッドは存在しないので、本サンプルではロックアウト状態の解除にのみ対応している。

 ユーザー情報を削除するには、MembershipUser.DeleteUserメソッドを使用する。

(2)ロール情報を取得/更新する

 ユーザーが特定のロールに属しているかどうかを判定するには、Rolesクラス(System.Web.Security名前空間)のIsUserInRoleメソッドを使用する必要がある。IsUserInRoleメソッドには、引数として先頭から「ユーザー名」「権限名」を指定することで、指定ユーザーがその権限(ロール)に属しているかをブール値で返すわけだ。

 ロールの追加/削除を行う場合にも、同様にRolesクラスを経由して、AddUserToRole/RemoveUserFromRoleメソッドを呼び出せばよい。それぞれ追加/削除の判定条件については、リスト内のコメントを参照いただくとよいだろう。

(3)プロファイル情報を取得/更新する

 最後に、プロファイル情報を取得/更新する方法だ。なお、プロファイル情報に関する詳細は、「TIPS:[ASP.NET]ユーザーごとのプロファイル情報を管理するには?」をご参照いただきたい。ここでは、ユーザーの漢字名を表すMyNameプロファイルがあらかじめ定義されているものとする。

 プロファイル情報を取得/設定するには、まず、ProfileBase.Createメソッドで、プロファイル情報を管理するためのProfileBaseオブジェクト(System.Web.Profile名前空間)を取得する必要がある。Createメソッドのパラメータには、プロファイル情報操作のキーとなるユーザー名を指定する。

 ProfileBaseオブジェクトが取得できてしまえば、あとはGetPropertyValue/SetPropertyValueメソッドでプロファイル値を取得/設定するだけだ。ただし、プロファイル値の更新を確定するには、最終的にSaveメソッドを呼び出す必要があるので注意してほしい。それまではプロファイル値はデータソースには反映されない。

2. 新規のWebフォームを作成する

 次に、データアクセス・コンポーネントを利用するためのWebフォーム(EditUser.aspx)を作成する。新規に.aspxファイルを作成したら、以下の画面の要領でGridViewコントロールをフォーム・デザイナ上に配置してほしい。

EditUser.aspxのフォーム・レイアウト
以下のコントロールを配置する。
  GridViewコントロール(grid)を配置(オート・フォーマットは「クラシック」)。

 ここで、GridViewコントロールに表示すべきデータソースの内容を定義しておく必要がある。データソースを定義するには、GridViewコントロールの右上から[GridViewタスク]メニューを表示して[データソースの選択]を選択すればよい。

 [データソース構成ウィザード]ダイアログが起動するので、以下の表の要領でデータソースの取得に必要な情報を設定する。データソース構成ウィザードの詳細については、先述の「データソース・コントロールでいってみよう(前編)」が詳しいので、こちらも併せて参照していただきたい。

項目 概要
データの種類 オブジェクト
データソースID ods
ビジネス オブジェクトの選択 User
データメソッドの定義 SELECT GetAllInfos()、戻り値 List<User>
UPDATE UpdateInfo(User usr)
DELETE DeleteInfo(User usr)
データソース構成ウィザードの設定

 一連の作業の後、[完了]ボタンをクリックすると、GridViewコントロールの下にObjectDataSourceコントロールが配置され、GridViewコントロールにもデータソースの内容がバインドされていることが確認できるはずだ。この状態で、GridView.DataKeyNamesプロパティ(キー列の名前)を「Name」に設定しておく。

 また、タスク・メニューから[編集を有効にする][削除を有効にする]にチェックを入れておこう。

3. GridViewコントロールの列を編集する

 GridViewコントロールの表示列を編集するには、コントロール右肩のタスク・メニューから[列の編集]を選択する。[フィールド]ダイアログが開くので、以下の表に従って列情報を入力する。フィールド編集に関しては、「データアクセス/データソース・コントロールを使い倒せ!」が詳しいので、併せてご参照いただきたい。

フィールド プロパティ名 概要
BoundField(Name) DataField Name
HeaderText ユーザ名
SortExpression Name
ReadOnly True
BoundField(KanjiName) DataField KanjiName
HeaderText ユーザ名(漢字)
SortExpression KanjiName
BoundField(Email) DataField Email
HeaderText E-Mailアドレス
SortExpression Email
CheckBoxField(IsLockedOut) DataField IsLockedOut
HeaderText ロック?
SortExpression IsLockedOut
CheckBoxField(IsAdmin) DataField IsAdmin
HeaderText 管理者
SortExpression IsAdmin
CommandField ButtonType Button
ShowEditButton True
ShowDeleteButton True
フィールド情報の設定

 以上で、一連の設定は完了だ。さっそく、サンプル・プログラムを実行し、実際の動作を確認してみよう。冒頭の画面のように、グリッド表上からユーザー情報を確認できること、また、それぞれのコマンドを選択することで更新や削除などの動作が正常に働くことを確認してほしい。End of Article

利用可能バージョン:.NET Framework 2.0
利用可能バージョン:.NET Framework 3.0
利用可能バージョン:.NET Framework 3.5
カテゴリ:Webフォーム 処理対象:認証
関連TIPS:[ASP.NET]セキュリティ・コントロールでログイン機能を作成するには?
関連TIPS:[ASP.NET]ユーザーごとのプロファイル情報を管理するには?

この記事と関連性の高い別の.NET TIPS
[ASP.NET]匿名ユーザーごとのプロファイル情報を保存するには?
[ASP.NET]ユーザーごとのプロファイル情報を管理するには?
[ASP.NET]GridViewコントロールでデータソースの内容を表示するには?
[ASP.NET]セキュリティ・コントロールでログイン機能を作成するには?
[ASP.NET AJAX]DragPanelコントロールのパネル位置を保存するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間