追加のユーザー情報を格納する (VB)
注意
この記事が作成されて以来、ASP.NET メンバーシップ プロバイダーは ASP.NET Identity に置き換えられました。 この記事の執筆時点で取り上げられたメンバーシップ プロバイダーではなく 、ASP.NET ID プラットフォームを使用するようにアプリを更新することを強くお勧めします。 ASP.NET ID には、ASP.NET メンバーシップ システムに比して、次のような多くの利点があります。
- パフォーマンスの向上
- 拡張性とテスト性の向上
- OAuth、OpenID Connect、および 2 要素認証のサポート
- クレームベースの ID のサポート
- ASP.Net Core との相互運用性の向上
このチュートリアルでは、非常に基本的なゲストブックアプリケーションを構築することで、この質問に答えます。 ここでは、データベース内のユーザー情報をモデル化するためのさまざまなオプションを確認し、このデータをメンバーシップ フレームワークによって作成されたユーザー アカウントに関連付ける方法を確認します。
はじめに
Asp。NET のメンバーシップ フレームワークは、ユーザーを管理するための柔軟なインターフェイスを提供します。 Membership API には、資格情報の検証、現在ログオンしているユーザーに関する情報の取得、新しいユーザー アカウントの作成、ユーザー アカウントの削除などのメソッドが含まれています。 Membership フレームワークの各ユーザー アカウントには、資格情報の検証と重要なユーザー アカウント関連のタスクの実行に必要なプロパティのみが含まれています。 これは、Membership フレームワークでユーザー アカウントをモデル化する クラスのMembershipUser
メソッドとプロパティによって証明されます。 このクラスには、、Email
、、 などのUserName
プロパティ、IsLockedOut
および などのGetPassword
UnlockUser
メソッドがあります。
多くの場合、アプリケーションでは、メンバーシップ フレームワークに含まれていない追加のユーザー情報を格納する必要があります。 たとえば、オンライン小売業者は、各ユーザーが自分の配送先住所と請求先住所、支払い情報、配送設定、連絡先電話番号を保存できるようにする必要がある場合があります。 さらに、システム内の各順序は、特定のユーザー アカウントに関連付けられます。
クラスにはMembershipUser
、 や DeliveryPreferences
PastOrders
などのPhoneNumber
プロパティは含まれません。 では、アプリケーションに必要なユーザー情報を追跡し、メンバーシップ フレームワークと統合するにはどうすればよいでしょうか。 このチュートリアルでは、非常に基本的なゲストブックアプリケーションを構築することで、この質問に答えます。 ここでは、データベース内のユーザー情報をモデル化するためのさまざまなオプションを確認し、このデータをメンバーシップ フレームワークによって作成されたユーザー アカウントに関連付ける方法を確認します。 それでは作業を始めましょう。
手順 1: ゲストブック アプリケーションのデータ モデルを作成する
データベース内のユーザー情報をキャプチャし、メンバーシップ フレームワークによって作成されたユーザー アカウントに関連付けるために使用できるさまざまな手法があります。 これらの手法を説明するには、チュートリアル Web アプリケーションを拡張して、何らかのユーザー関連データをキャプチャする必要があります。 (現在、アプリケーションのデータ モデルには、 で SqlMembershipProvider
必要なアプリケーション サービス テーブルのみが含まれています)。
認証されたユーザーがコメントを残すことができる非常に単純なゲストブック アプリケーションを作成しましょう。 ゲストブックのコメントを保存するだけでなく、各ユーザーが自分のホーム タウン、ホームページ、署名を保存できるようにしましょう。 指定した場合、ユーザーのホーム タウン、ホームページ、署名は、ゲストブックに残した各メッセージに表示されます。
テーブルのGuestbookComments
追加
ゲストブックのコメントをキャプチャするには、 という名前GuestbookComments
のデータベース テーブルを作成し、 などのBody
CommentId
Subject
CommentDate
列を含む必要があります。 また、テーブル内の各レコードで、コメントを GuestbookComments
残したユーザーを参照する必要があります。
このテーブルをデータベースに追加するには、Visual Studio のデータベース エクスプローラーに移動し、データベースをドリルダウンしますSecurityTutorials
。 [テーブル] フォルダーを右クリックし、[新しいテーブルの追加] を選択します。 これにより、新しいテーブルの列を定義できるインターフェイスが表示されます。
図 1: データベースに新しいテーブルを SecurityTutorials
追加する (フルサイズの画像を表示するをクリックします)
次に、 の列を GuestbookComments
定義します。 最初に、 型uniqueidentifier
の という名前CommentId
の列を追加します。 この列はゲストブック内の各コメントを一意に識別するため、 を禁止 NULL
し、テーブルの主キーとしてマークします。 各 のフィールドに値CommentId
を指定するのではなく、列の既定値を に設定することで、このフィールドに対して新しいuniqueidentifier
値NEWID()
を自動的にINSERT
生成する必要があることを示すことができます。INSERT
この最初のフィールドを追加し、それを主キーとしてマークし、既定値を設定すると、画面は図 2 に示すスクリーン ショットのようになります。
図 2: という名前 CommentId
のプライマリ列を追加する (フルサイズの画像を表示する] をクリックします)
次に、 型nvarchar(50)
という名前Subject
の列と 型 という名前Body
の列を追加し、両方のnvarchar(MAX)
列で をNULL
許可しないようにします。 その後、 型の という名前 CommentDate
の列を追加します datetime
。 を禁止 NULL
し、列の CommentDate
既定値を に getdate()
設定します。
残っているのは、ユーザー アカウントを各ゲストブック コメントに関連付ける列を追加することです。 1 つのオプションは、 型の という名前 UserName
の列を追加することです nvarchar(256)
。 これは、 以外のメンバーシップ プロバイダーを使用する場合に適した SqlMembershipProvider
選択肢です。 ただし、このチュートリアル シリーズのように を SqlMembershipProvider
使用する場合、 UserName
テーブル内の aspnet_Users
列は一意であるとは限りません。 aspnet_Users
テーブルの主キーは でUserId
、型uniqueidentifier
は です。 そのため、テーブルには GuestbookComments
型 uniqueidentifier
(値を許可しない) という名前UserId
の列がNULL
必要です。 先に進み、この列を追加します。
注意
「SQL Serverチュートリアルでのメンバーシップ スキーマの作成」で説明したように、Membership フレームワークは、異なるユーザー アカウントを持つ複数の Web アプリケーションが同じユーザー ストアを共有できるように設計されています。 これは、ユーザー アカウントを異なるアプリケーションにパーティション分割することによって行われます。 また、各ユーザー名はアプリケーション内で一意であることが保証されますが、同じユーザー ストアを使用する異なるアプリケーションで同じユーザー名を使用できます。 フィールドと ApplicationId
フィールドのaspnet_Users
テーブルUserName
には複合UNIQUE
制約がありますが、フィールドだけのUserName
制約はありません。 したがって、aspnet_Users テーブルに同じ UserName
値を持つ 2 つ以上のレコードが含まれる可能性があります。 ただし、テーブルUserId
のUNIQUE
フィールドには制約aspnet_Users
があります (主キーであるため)。 制約がないとUNIQUE
、 テーブルと aspnet_Users
テーブルの間に外部キー制約を確立できないため、制約はGuestbookComments
重要です。
列を追加したら UserId
、ツール バーの [保存] アイコンをクリックしてテーブルを保存します。 新しいテーブルに という名前を付けます GuestbookComments
。
テーブルに関する最後の問題が GuestbookComments
1 つあり、列と列の間に外部キー制約を作成するGuestbookComments.UserId
aspnet_Users.UserId
必要があります。 これを実現するには、ツール バーの [リレーションシップ] アイコンをクリックして、[外部キーリレーションシップ] ダイアログ ボックスを起動します。 (または、[テーブル Designer] メニューに移動し、[リレーションシップ] を選択して、このダイアログ ボックスを起動することもできます)。
[外部キーリレーションシップ] ダイアログ ボックスの左下隅にある [追加] ボタンをクリックします。 これにより、新しい外部キー制約が追加されますが、リレーションシップに関与するテーブルを定義する必要があります。
図 3: [外部キーリレーションシップ] ダイアログ ボックスを使用してテーブルの外部キー制約を管理する (フルサイズの画像を表示する をクリックします)
次に、右側の [テーブルと列の仕様] 行の省略記号アイコンをクリックします。 これにより、[テーブルと列] ダイアログ ボックスが起動し、主キー テーブルと列、およびテーブルの外部キー列を GuestbookComments
指定できます。 特に、主キー テーブルと列として と UserId
を選択しUserId
、テーブルからGuestbookComments
外部キー列として を選択aspnet_Users
します (図 4 を参照)。 主キー テーブルと外部キー テーブルと列を定義したら、[OK] をクリックして [外部キーリレーションシップ] ダイアログ ボックスに戻ります。
図 4: テーブルと GuesbookComments
テーブルの間に外部キー制約をaspnet_Users
設定する (フルサイズの画像を表示する をクリックします)
この時点で、外部キー制約が確立されました。 この制約が存在すると、存在しないユーザー アカウントを参照するゲストブック エントリが存在しないことを保証することで、2 つのテーブル間の リレーショナル整合性 が確保されます。 既定では、外部キー制約では、対応する子レコードがある場合、親レコードの削除は禁止されます。 つまり、ユーザーが 1 つ以上のゲストブック コメントを作成し、そのユーザー アカウントを削除しようとすると、ゲストブックのコメントが最初に削除されない限り、削除は失敗します。
外部キー制約は、親レコードが削除されたときに関連付けられている子レコードを自動的に削除するように構成できます。 つまり、ユーザー アカウントが削除されたときにユーザーのゲストブック エントリが自動的に削除されるように、この外部キー制約を設定できます。 これを実現するには、"INSERT and UPDATE の仕様" セクションを展開し、"ルールの削除" プロパティを Cascade に設定します。
図 5: 削除を連鎖するように外部キー制約を構成する (フルサイズの画像を表示する をクリックします)
外部キー制約を保存するには、[閉じる] ボタンをクリックして外部キーリレーションシップから終了します。 次に、ツール バーの [保存] アイコンをクリックして、テーブルとこのリレーションシップを保存します。
ユーザーのホーム タウン、ホームページ、署名の保存
この表は GuestbookComments
、ユーザー アカウントと一対多リレーションシップを共有する情報を格納する方法を示しています。 各ユーザー アカウントには任意の数のコメントが関連付けられている可能性があるため、このリレーションシップは、各コメントを特定のユーザーにリンクする列を含むコメントのセットを保持するテーブルを作成することによってモデル化されます。 をSqlMembershipProvider
使用する場合、このリンクは、 型uniqueidentifier
という名前UserId
の列と、この列と の間に外部キー制約を作成することによって最適にaspnet_Users.UserId
確立されます。
ここでは、ユーザーのホーム タウン、ホームページ、署名を格納するために、各ユーザー アカウントに 3 つの列を関連付ける必要があります。これは、ゲストブックのコメントに表示されます。 これを行うには、さまざまな方法があります。
に新しい列を追加する
aspnet_Users
またはaspnet_Membership
テーブル。 このアプローチは によってSqlMembershipProvider
使用されるスキーマを変更するため、お勧めしません。 この決定は、道を下ってあなたを悩ませるために戻ってくるかもしれません。 たとえば、将来のバージョンの ASP.NET で別SqlMembershipProvider
のスキーマが使用されている場合はどうなりますか。 Microsoft には、ASP.NET 2.0SqlMembershipProvider
データを新しいスキーマに移行するためのツールが含まれている場合がありますが、ASP.NET 2.0SqlMembershipProvider
スキーマを変更した場合、そのような変換が不可能な場合があります。ASP を使用します。NET のプロファイル フレームワーク。ホーム タウン、ホームページ、署名のプロファイル プロパティを定義します。 ASP.NET には、追加のユーザー固有のデータを格納するように設計されたプロファイル フレームワークが含まれています。 メンバーシップ フレームワークと同様に、プロファイル フレームワークはプロバイダー モデルの上に構築されます。 .NET Framework
SqlProfileProvider
には、SQL Server データベースにプロファイル データを格納する が付属しています。 実際、このデータベースには、() によってSqlProfileProvider
aspnet_Profile
使用されるテーブルが既に含まれています。これは、SQL Serverチュートリアルのメンバーシップ スキーマの作成にアプリケーション サービスを追加したときに追加されました。
プロファイル フレームワークのメインの利点は、開発者が でプロファイル プロパティを定義できる点です。基になるデータ ストアとの間でWeb.config
プロファイル データをシリアル化するためのコードを記述する必要はありません。 つまり、プロファイル プロパティのセットを定義し、コードで操作することは非常に簡単です。 ただし、バージョン管理に関してはプロファイル システムが必要な部分が多いので、後で新しいユーザー固有のプロパティを追加する必要があるアプリケーションや、既存のプロパティを削除または変更する必要があるアプリケーションがある場合は、プロファイル フレームワークが最適なオプションではない可能性があります。 さらに、プロファイル プロパティはSqlProfileProvider
高度に非正規化された方法で格納されるため、プロファイル データに対して直接クエリを実行することは不可能になります (たとえば、ニューヨークのホーム タウンを持つユーザーの数など)。
プロファイル フレームワークの詳細については、このチュートリアルの最後にある「さらに読む」セクションを参照してください。データベース内の新しいテーブルにこれら 3 つの列を追加し、このテーブルと
aspnet_Users
。 この方法では、プロファイル フレームワークよりも少し多くの作業が必要ですが、データベースで追加のユーザー プロパティをモデル化する方法に最大限の柔軟性が提供されます。 これは、このチュートリアルで使用するオプションです。
という名前 UserProfiles
の新しいテーブルを作成して、各ユーザーのホーム タウン、ホームページ、署名を保存します。 [データベース エクスプローラー] ウィンドウで [テーブル] フォルダーを右クリックし、新しいテーブルを作成することを選択します。 最初の列 UserId
に名前を付け、その型を に uniqueidentifier
設定します。 値を禁止 NULL
し、列を主キーとしてマークします。 次に、 型の というHomeTown
名前の列を追加します。型nvarchar(50)
nvarchar(100)
は 。 HomepageUrl
型は nvarchar(500)
Signature です。 これら 3 つの列はそれぞれ、値を NULL
受け取ることができます。
図 6: テーブルを作成する UserProfiles
(クリックするとフルサイズの画像が表示されます)
テーブルを保存し、 という名前を付けます UserProfiles
。 最後に、テーブルUserId
のフィールドとフィールドの間にUserProfiles
外部キー制約をaspnet_Users.UserId
設定します。 テーブルと aspnet_Users
テーブルの間の外部キー制約と同様にGuestbookComments
、この制約は連鎖削除されます。 のUserId
UserProfiles
フィールドは主キーであるため、これにより、各ユーザー アカウントのテーブルにUserProfiles
複数のレコードが存在することが保証されます。 この種類のリレーションシップは、一対一と呼ばれます。
データ モデルが作成されたので、それを使用する準備ができました。 手順 2 と 3 では、現在ログオンしているユーザーがホーム タウン、ホームページ、署名情報を表示および編集する方法について説明します。 手順 4 では、認証されたユーザーがゲストブックに新しいコメントを送信し、既存のコメントを表示するためのインターフェイスを作成します。
手順 2: ユーザーのホーム タウン、ホームページ、署名を表示する
現在ログオンしているユーザーが自分のホーム タウン、ホームページ、署名情報を表示および編集できるようにするには、さまざまな方法があります。 TextBox コントロールと Label コントロールを使用してユーザー インターフェイスを手動で作成することも、DetailsView コントロールなどのデータ Web コントロールのいずれかを使用することもできます。 データベースSELECT
とUPDATE
ステートメントを実行するために、ページの分離コード クラスに ADO.NET コードを記述するか、または SqlDataSource で宣言型アプローチを採用することもできます。 アプリケーションには階層化されたアーキテクチャが含まれているのが理想的です。このアーキテクチャは、ページの分離コード クラスからプログラムで呼び出すか、ObjectDataSource コントロールを介して宣言によって呼び出すことができます。
このチュートリアル シリーズではフォーム認証、承認、ユーザー アカウント、ロールに焦点を当てているため、これらのさまざまなデータ アクセス オプションや、ASP.NET ページから直接 SQL ステートメントを実行するよりも階層型アーキテクチャが優先される理由については詳しく説明しません。 最も簡単で簡単なオプションである DetailsView と SqlDataSource を使用して説明しますが、説明されている概念は、代替の Web コントロールとデータ アクセス ロジックに確実に適用できます。 ASP.NET でのデータの操作の詳細については、「ASP.NET 2.0 でのデータの操作 」チュートリアル シリーズを参照してください。
フォルダー内のページをMembership
AdditionalUserInfo.aspx
開き、DetailsView コントロールをページに追加し、ID プロパティを にUserProfile
設定し、そのプロパティとHeight
プロパティをWidth
クリアします。 DetailsView のスマート タグを展開し、新しいデータ ソース コントロールにバインドすることを選択します。 これにより、DataSource 構成ウィザードが起動します (図 7 を参照)。 最初の手順では、データ ソースの種類を指定するように求められます。 データベースに直接接続SecurityTutorials
するため、[ データベース] アイコンを選択し、 を としてUserProfileDataSource
指定ID
します。
図 7: 名前付きの UserProfileDataSource
新しい SqlDataSource コントロールを追加する (フルサイズの画像を表示する をクリックします)
次の画面では、データベースを使用するように求められます。 データベースの 接続文字列 は既にWeb.config
SecurityTutorials
定義されています。 この接続文字列名 – SecurityTutorialsConnectionString
は、ドロップダウン リストに含まれている必要があります。 このオプションを選択し、[次へ] をクリックします。
図 8: Drop-Down リストから選択 SecurityTutorialsConnectionString
する (フルサイズの画像を表示する をクリックします)
後続の画面では、クエリを実行するテーブルと列を指定するように求められます。 UserProfiles
ドロップダウン リストからテーブルを選択し、すべての列をチェックします。
図 9: テーブルから UserProfiles
すべての列を取り戻す (フルサイズの画像を表示する をクリックします)
図 9 の 現在のクエリ は、 のすべての UserProfiles
レコードを返しますが、現在ログオンしているユーザーのレコードにのみ関心があります。 句を WHERE
追加するには、ボタンを WHERE
クリックして [句の追加 WHERE
] ダイアログ ボックスを表示します (図 10 を参照)。 ここでは、フィルターを適用する列、演算子、フィルター パラメーターのソースを選択できます。 列として を選択し、演算子として "=" を選択 UserId
します。
残念ながら、現在ログオンしているユーザー UserId
の値を返す組み込みのパラメーター ソースはありません。 この値をプログラムで取得する必要があります。 そのため、[ソース] ドロップダウン リストを [なし] に設定し、[追加] ボタンをクリックしてパラメーターを追加し、[OK] をクリックします。
図 10: 列にフィルター パラメーターを追加する UserId
(フルサイズの画像を表示する をクリックします)
[OK] をクリックすると、図 9 に示す画面に戻ります。 ただし、今回は、画面の下部にある SQL クエリに 句を WHERE
含める必要があります。 [次へ] をクリックして、[クエリのテスト] 画面に移動します。 ここでは、クエリを実行して結果を確認できます。 [完了] をクリックしてウィザードを終了します。
DataSource 構成ウィザードが完了すると、ウィザードで指定された設定に基づいて SqlDataSource コントロールが作成されます。 さらに、SqlDataSource SelectCommand
の によって返される各列の DetailsView に BoundFields を手動で追加します。 ユーザーはこの値を UserId
知る必要がないため、DetailsView にフィールドを表示する必要はありません。 このフィールドは、DetailsView コントロールの宣言型マークアップから直接削除するか、スマート タグから [フィールドの編集] リンクをクリックして削除できます。
この時点で、ページの宣言型マークアップは次のようになります。
<asp:DetailsView ID="UserProfile" runat="server"
AutoGenerateRows="False" DataKeyNames="UserId"
DataSourceID="UserProfileDataSource">
<Fields>
<asp:BoundField DataField="HomeTown" HeaderText="HomeTown"
SortExpression="HomeTown" />
<asp:BoundField DataField="HomepageUrl" HeaderText="HomepageUrl"
SortExpression="HomepageUrl" />
<asp:BoundField DataField="Signature" HeaderText="Signature"
SortExpression="Signature" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="UserProfileDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:SecurityTutorialsConnectionString %>"
SelectCommand="SELECT [UserId], [HomeTown], [HomepageUrl], [Signature] FROM
[UserProfiles] WHERE ([UserId] = @UserId)">
<SelectParameters>
<asp:Parameter Name="UserId" Type="Object" />
</SelectParameters>
</asp:SqlDataSource>
データを選択する前に、SqlDataSource コントロールの UserId
パラメーターを現在ログインしているユーザーの UserId
パラメーターにプログラムで設定する必要があります。 これを行うには、SqlDataSource のイベントのイベント ハンドラーを作成し、そこに次の Selecting
コードを追加します。
Protected Sub UserProfileDataSource_Selecting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs) Handles UserProfileDataSource.Selecting
' Get a reference to the currently logged on user
Dim currentUser As MembershipUser = Membership.GetUser()
' Determine the currently logged on user's UserId value
Dim currentUserId As Guid = CType(currentUser.ProviderUserKey, Guid)
' Assign the currently logged on user's UserId to the @UserId parameter
e.Command.Parameters("@UserId").Value = currentUserId
End Sub
上記のコードは、まず、 クラスGetUser
の メソッドを呼び出して、現在ログオンしているユーザーへの参照をMembership
取得します。 これにより、 ProviderUserKey
プロパティに がMembershipUser
含まれる オブジェクトが返されますUserId
。 その UserId
後、値は SqlDataSource @UserId
のパラメーターに割り当てられます。
注意
メソッドは Membership.GetUser()
、現在ログオンしているユーザーに関する情報を返します。 匿名ユーザーがページにアクセスしている場合は、 の Nothing
値が返されます。 このような場合、 プロパティを NullReferenceException
読み取ろうとすると、次のコード行で が ProviderUserKey
発生します。 もちろん、認証されたユーザーのみがこのフォルダー内の AdditionalUserInfo.aspx
ASP.NET リソースにアクセスできるように、前のチュートリアルで URL 承認を構成したため、ページに Nothing が返されることを心配する必要Membership.GetUser()
はありません。 匿名アクセスが許可されているページで現在ログオンしているユーザーに関する情報にアクセスする必要がある場合は、プロパティを参照する前にMembershipUser
、メソッドから返されたオブジェクトが Nothing ではないことをGetUser()
チェックしてください。
ブラウザーを使用してページに AdditionalUserInfo.aspx
アクセスすると、テーブルに行を追加していないため、空白のページが UserProfiles
表示されます。 手順 6 では、CreateUserWizard コントロールをカスタマイズして、新しいユーザー アカウントの作成時にテーブルに新しい行を自動的に追加する UserProfiles
方法について説明します。 ただし、ここではテーブルに手動でレコードを作成する必要があります。
Visual Studio の [データベース] エクスプローラーに移動し、[テーブル] フォルダーを展開します。 テーブルを右クリックし、[テーブル データの aspnet_Users
表示] を選択してテーブル内のレコードを表示します。テーブルに対 UserProfiles
して同じことを行います。 図 11 は、垂直方向に並べて表示された場合のこれらの結果を示しています。 私のデータベースには現在 aspnet_Users
、Bruce、Fred、Titoのレコードがありますが、テーブルに UserProfiles
レコードはありません。
図 11: テーブルと UserProfiles
テーブルのaspnet_Users
内容が表示されます (クリックするとフルサイズの画像が表示されます)
、、および フィールドの値をUserProfiles
手動で入力して、テーブルに新しいレコードをSignature
HomeTown
HomepageUrl
追加します。 新しいUserProfiles
レコードで有効なUserId
値を取得する最も簡単な方法は、テーブル内の特定のユーザー アカウントからフィールドをaspnet_Users
選択UserId
し、 のフィールドUserProfiles
にUserId
コピーして貼り付けることです。 図 12 は、Bruce に UserProfiles
新しいレコードが追加された後のテーブルを示しています。
図 12: Bruce の にレコードが追加 UserProfiles
されました (フルサイズの画像を表示する をクリックします)
に戻り、 AdditionalUserInfo.aspx page
Bruce としてログインします。 図 13 に示すように、Bruce の設定が表示されます。
図 13: 現在アクセスしているユーザーの設定が表示されている (フルサイズの画像を表示する をクリックします)
注意
次に進み、各メンバーシップ ユーザーのテーブルにレコードを UserProfiles
手動で追加します。 手順 6 では、CreateUserWizard コントロールをカスタマイズして、新しいユーザー アカウントの作成時にテーブルに新しい行を自動的に追加する UserProfiles
方法について説明します。
手順 3: ユーザーがホーム タウン、ホームページ、署名を編集できるようにする
この時点で、現在ログインしているユーザーはホーム タウン、ホームページ、署名の設定を表示できますが、まだ変更することはできません。 データを編集できるように DetailsView コントロールを更新しましょう。
最初に、実行するステートメントとそれに対応するパラメーターを指定してUPDATE
、SqlDataSource の を追加UpdateCommand
する必要があります。 SqlDataSource を選択し、プロパティ ウィンドウから UpdateQuery プロパティの横にある省略記号をクリックして、[コマンドとパラメーターのエディター] ダイアログ ボックスを表示します。 テキスト ボックスに次 UPDATE
のステートメントを入力します。
UPDATE UserProfiles SET
HomeTown = @HomeTown,
HomepageUrl = @HomepageUrl,
Signature = @Signature
WHERE UserId = @UserId
次に、[パラメーターの更新] ボタンをクリックします。これにより、 ステートメント内の各パラメーターのパラメーターが SqlDataSource コントロールの UpdateParameters
コレクションに UPDATE
作成されます。 すべてのパラメーターのソースを [なし] に設定したまま、[OK] ボタンをクリックしてダイアログ ボックスを完了します。
図 14: SqlDataSource の と UpdateParameters
を指定します (フルサイズのUpdateCommand
画像を表示するには、ここをクリックします)
SqlDataSource コントロールに追加されたため、DetailsView コントロールで編集をサポートできるようになりました。 DetailsView のスマート タグから、[編集を有効にする] チェック ボックスをチェックします。 これにより、プロパティが True に設定された CommandField がコントロールの Fields
コレクション ShowEditButton
に追加されます。 DetailsView が読み取り専用モードで表示されている場合は [編集] ボタンが表示され、編集モードで表示される場合は [更新] ボタンと [キャンセル] ボタンが表示されます。 ただし、ユーザーに [編集] をクリックさせる代わりに、DetailsView コントロールDefaultMode
の プロパティEdit
を に設定することで、DetailsView を "常に編集可能" 状態でレンダリングできます。
これらの変更により、DetailsView コントロールの宣言型マークアップは次のようになります。
<asp:DetailsView ID="UserProfile" runat="server"
AutoGenerateRows="False" DataKeyNames="UserId"
DataSourceID="UserProfileDataSource" DefaultMode="Edit">
<Fields>
<asp:BoundField DataField="HomeTown" HeaderText="HomeTown"
SortExpression="HomeTown" />
<asp:BoundField DataField="HomepageUrl" HeaderText="HomepageUrl"
SortExpression="HomepageUrl" />
<asp:BoundField DataField="Signature" HeaderText="Signature"
SortExpression="Signature" />
<asp:CommandField ShowEditButton="True" />
</Fields>
</asp:DetailsView>
CommandField と プロパティの追加に DefaultMode
注意してください。
先に進み、ブラウザーを使用してこのページをテストします。 で対応するレコードを持つユーザーと一緒に UserProfiles
アクセスすると、ユーザーの設定が編集可能なインターフェイスに表示されます。
図 15: DetailsView は編集可能なインターフェイスをレンダリングします (フルサイズの画像を表示するには、ここをクリックします)
値を変更し、[更新] ボタンをクリックしてみてください。 何も起こっていないかのように見えます。 ポストバックがあり、値はデータベースに保存されますが、保存が発生したという視覚的なフィードバックはありません。
これを解決するには、Visual Studio に戻り、DetailsView の上にラベル コントロールを追加します。 を ID
に SettingsUpdatedMessage
設定し、その Text
プロパティを "設定が更新されました" に設定し、その Visible
プロパティと EnableViewState
プロパティを に設定 False
します。
<asp:Label ID="SettingsUpdatedMessage" runat="server"
Text="Your settings have been updated."
EnableViewState="false"
Visible="false">
</asp:Label>
DetailsView が SettingsUpdatedMessage
更新されるたびに、ラベルを表示する必要があります。 これを実現するには、DetailsView のイベントのイベント ハンドラーを作成し、次の ItemUpdated
コードを追加します。
Protected Sub UserProfile_ItemUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdatedEventArgs) Handles UserProfile.ItemUpdated
SettingsUpdatedMessage.Visible = True
End Sub
ブラウザーからページに AdditionalUserInfo.aspx
戻り、データを更新します。 今回は、役に立つステータス メッセージが表示されます。
図 16: 設定が更新されたときに短いメッセージが表示される (フルサイズの画像を表示する をクリックします)
注意
DetailsView コントロールの編集インターフェイスを使用すると、多くの処理が必要になります。 標準サイズのテキスト ボックスを使用しますが、[署名] フィールドはおそらく複数行のテキスト ボックスである必要があります。 RegularExpressionValidator を使用して、ホームページの URL が入力された場合は、"http://" または "https://" で始まっていることを確認する必要があります。 さらに、DetailsView コントロールのプロパティは DefaultMode
に Edit
設定されているため、[キャンセル] ボタンは何も行いません。 削除するか、クリックすると、ユーザーを他のページ (など ~/Default.aspx
) にリダイレクトする必要があります。 これらの機能強化は、読者の演習として残しておきます。
マスター ページのページへのAdditionalUserInfo.aspx
リンクの追加
現在、この Web サイトではページへのリンクは AdditionalUserInfo.aspx
提供されていません。 アクセスする唯一の方法は、ブラウザーのアドレス バーにページの URL を直接入力することです。 マスター ページでこのページへのリンクを Site.master
追加しましょう。
マスター ページの ContentPlaceHolder に LoginView Web コントロール LoginContent
が含まれており、認証された訪問者と匿名の訪問者に対して異なるマークアップが表示されることを思い出してください。 LoginView コントロールの LoggedInTemplate
を更新して、ページへのリンクを AdditionalUserInfo.aspx
含めます。 これらの変更を行った後、LoginView コントロールの宣言型マークアップは次のようになります。
<asp:LoginView ID="LoginView1" runat="server">
<LoggedInTemplate>
Welcome back,
<asp:LoginName ID="LoginName1" runat="server" />.
<br />
<asp:HyperLink ID="lnkUpdateSettings" runat="server"
NavigateUrl="~/Membership/AdditionalUserInfo.aspx">
Update Your Settings</asp:HyperLink>
</LoggedInTemplate>
<AnonymousTemplate>
Hello, stranger.
</AnonymousTemplate>
</asp:LoginView>
HyperLink コントロールが lnkUpdateSettings
に追加されていることに注意してください LoggedInTemplate
。 このリンクを設定すると、認証されたユーザーはページにすばやく移動して、ホーム タウン、ホームページ、署名の設定を表示および変更できます。
手順 4: 新しいゲストブック コメントの追加
この Guestbook.aspx
ページでは、認証されたユーザーがゲストブックを表示し、コメントを残すことができます。 新しいゲストブックコメントを追加するインターフェイスの作成から始めましょう。
Visual Studio でページを Guestbook.aspx
開き、新しいコメントの件名と本文用の 2 つの TextBox コントロールで構成されるユーザー インターフェイスを構築します。 最初の TextBox コントロールの ID
プロパティを に Subject
設定し、その Columns
プロパティを 40 に設定し、second の ID
を に Body
、その TextMode
を に MultiLine
、プロパティ Width
と Rows
プロパティをそれぞれ "95%" と 8 に設定します。 ユーザー インターフェイスを完了するには、 という名前 PostCommentButton
の Button Web コントロールを追加し、その Text
プロパティを "コメントの投稿" に設定します。
各ゲストブック コメントには件名と本文が必要であるため、各 TextBoxes に RequiredFieldValidator を追加します。 これらのコントロールの プロパティを ValidationGroup
"EnterComment" に設定します。同様に、コントロールの ValidationGroup
プロパティを "EnterComment" に設定PostCommentButton
します。 ASP の詳細については、 を参照してください。NET の検証コントロールでは、ASP.NET でフォーム検証をチェック。
ユーザー インターフェイスを作成した後、ページの宣言型マークアップは次のようになります。
<h3>Leave a Comment</h3>
<p>
<b>Subject:</b>
<asp:RequiredFieldValidator ID="SubjectReqValidator" runat="server"
ErrorMessage="You must provide a value for Subject"
ControlToValidate="Subject" ValidationGroup="EnterComment">
</asp:RequiredFieldValidator><br />
<asp:TextBox ID="Subject" Columns="40" runat="server"></asp:TextBox>
</p>
<p>
<b>Body:</b>
<asp:RequiredFieldValidator ID="BodyReqValidator" runat="server"
ControlToValidate="Body"
ErrorMessage="You must provide a value for Body" ValidationGroup="EnterComment">
</asp:RequiredFieldValidator><br />
<asp:TextBox ID="Body" TextMode="MultiLine" Width="95%"
Rows="8" runat="server"></asp:TextBox>
</p>
<p>
<asp:Button ID="PostCommentButton" runat="server"
Text="Post Your Comment"
ValidationGroup="EnterComment" />
</p>
ユーザー インターフェイスが完了したら、次のタスクは、 がクリックされたときにPostCommentButton
テーブルに新しいレコードをGuestbookComments
挿入することです。 これは、さまざまな方法で実現できます。ボタンのClick
イベント ハンドラーでコード ADO.NET 記述できます。SqlDataSource コントロールをページに追加し、その InsertCommand
を構成し、イベント ハンドラーからClick
メソッドをInsert
呼び出すことができます。または、新しいゲストブック コメントを挿入する中間層を構築し、イベント ハンドラーからこの機能をClick
呼び出すことができます。 手順 3 で SqlDataSource の使用を見たので、ここで ADO.NET コードを使用しましょう。
注意
Microsoft SQL Server データベースからプログラムでデータにアクセスするために使用される ADO.NET クラスは、 名前空間にありますSystem.Data.SqlClient
。 この名前空間は、ページの分離コード クラス (つまり) Imports System.Data.SqlClient
にインポートする必要がある場合があります。
の イベントのイベント ハンドラーをPostCommentButton
Click
作成し、次のコードを追加します。
Protected Sub PostCommentButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles PostCommentButton.Click
If Not Page.IsValid Then Exit Sub
' Determine the currently logged on user's UserId
Dim currentUser As MembershipUser = Membership.GetUser()
Dim currentUserId As Guid = CType(currentUser.ProviderUserKey, Guid)
' Insert a new record into GuestbookComments
Dim connectionString As String =
ConfigurationManager.ConnectionStrings("SecurityTutorialsConnectionString").ConnectionString
Dim insertSql As String = "INSERT INTO GuestbookComments(Subject, Body, UserId)
VALUES(@Subject, @Body, @UserId)"
Using myConnection As New SqlConnection(connectionString)
myConnection.Open()
Dim myCommand As New SqlCommand(insertSql, myConnection)
myCommand.Parameters.AddWithValue("@Subject", Subject.Text.Trim())
myCommand.Parameters.AddWithValue("@Body", Body.Text.Trim())
myCommand.Parameters.AddWithValue("@UserId", currentUserId)
myCommand.ExecuteNonQuery()
myConnection.Close()
End Using
' "Reset" the Subject and Body TextBoxes
Subject.Text = String.Empty
Body.Text = String.Empty
End Sub
イベント ハンドラーは Click
、ユーザーが指定したデータが有効であることを確認することから始めます。 そうでない場合、イベント ハンドラーはレコードを挿入する前に終了します。 指定されたデータが有効であると仮定すると、現在ログオンしているユーザーの UserId
値が取得され、ローカル変数に currentUserId
格納されます。 にレコードGuestbookComments
を挿入するときに値をUserId
指定する必要があるため、この値が必要です。
その後、データベースの接続文字列SecurityTutorials
が からWeb.config
取得され、INSERT
SQL ステートメントが指定されます。 SqlConnection
その後、オブジェクトが作成されて開かれます。 次に SqlCommand
、オブジェクトが構築され、クエリで使用されるパラメーターの INSERT
値が割り当てられます。 INSERT
ステートメントが実行され、接続が閉じられます。 イベント ハンドラーの最後に、 Subject
プロパティと Body
TextBoxes プロパティ Text
がクリアされるため、ユーザーの値はポストバック全体で保持されません。
先に進み、ブラウザーでこのページをテストします。 このページはフォルダー内にありますので Membership
、匿名の訪問者はアクセスできません。 そのため、最初にログオンする必要があります (まだログオンしていない場合)。 と Body
TextBoxes に値をSubject
入力し、ボタンをPostCommentButton
クリックします。 これにより、新しいレコードが に GuestbookComments
追加されます。 ポストバックでは、指定した件名と本文が TextBoxes からワイプされます。
ボタンをクリックすると、 PostCommentButton
コメントがゲストブックに追加されたという視覚的なフィードバックはありません。 既存のゲストブックコメントを表示するには、このページを更新する必要があります。これは手順 5 で行います。 これを完了すると、追加したコメントがコメントの一覧に表示され、適切な視覚的フィードバックが提供されます。 ここでは、テーブルの内容を調べて、ゲストブックの GuestbookComments
コメントが保存されたことを確認します。
図 17 は、2 つのコメントが残された後の GuestbookComments
テーブルの内容を示しています。
図 17: テーブルにゲストブックのコメントを GuestbookComments
表示できます (フルサイズの画像を表示する をクリックします)
注意
ユーザーが危険なマークアップ (HTML など) を含むゲストブック コメントを挿入しようとすると、ASP.NET は を HttpRequestValidationException
スローします。 この例外の詳細、スローされる理由、およびユーザーが潜在的に危険な値を送信できるようにする方法については、 要求検証に関するホワイトペーパーを参照してください。
手順 5: 既存のゲストブックのコメントを一覧表示する
コメントを残すだけでなく、ページにアクセスする Guestbook.aspx
ユーザーもゲストブックの既存のコメントを表示できる必要があります。 これを行うには、ページの下部に という名前 CommentList
の ListView コントロールを追加します。
注意
ListView コントロールは、ASP.NET バージョン 3.5 の新機能です。 これは、非常にカスタマイズ可能で柔軟なレイアウトで項目の一覧を表示するように設計されています。それでも、GridView のような組み込みの編集、挿入、削除、ページング、並べ替え機能が提供されます。 ASP.NET 2.0 を使用している場合は、代わりに DataList コントロールまたは Repeater コントロールを使用する必要があります。 ListView の使用の詳細については、Scott Guthrie のブログ エントリ、asp:ListView コントロール、および ListView コントロールを使用したデータの表示に関する記事を参照してください。
ListView のスマート タグを開き、[データ ソースの選択] ドロップダウン リストからコントロールを新しいデータ ソースにバインドします。 手順 2 で説明したように、データ ソース構成ウィザードが起動します。 [データベース] アイコンを選択し、結果の SqlDataSource CommentsDataSource
に名前を付け、[OK] をクリックします。 次にSecurityTutorialsConnectionString
、ドロップダウン リストから接続文字列を選択し、[次へ] をクリックします。
手順 2 のこの時点で、クエリを実行するデータを指定しました。そのためには、ドロップダウン リストからテーブルを選択 UserProfiles
し、返す列を選択します (図 9 を参照)。 ただし、今回は、 から GuestbookComments
レコードだけでなく、コメント者のホーム タウン、ホームページ、署名、ユーザー名も取り戻す SQL ステートメントを作成したいと考えています。 そのため、[カスタム SQL ステートメントまたはストアド プロシージャを指定する] ラジオ ボタンを選択し、[次へ] をクリックします。
これにより、[カスタム ステートメントまたはストアド プロシージャの定義] 画面が表示されます。 [クエリ ビルダー] ボタンをクリックして、クエリをグラフィカルに作成します。 クエリ ビルダーは、クエリを実行するテーブルの指定を求めるメッセージを表示することから始まります。 、UserProfiles
、および の各テーブルをGuestbookComments
aspnet_Users
選択し、[OK] をクリックします。 これにより、3 つのテーブルすべてがデザイン サーフェイスに追加されます。 、UserProfiles
、および aspnet_Users
の各テーブルにはGuestbookComments
外部キー制約があるため、クエリ ビルダーはこれらのテーブルを自動的JOIN
に作成します。
残っているのは、返す列を指定することです。 テーブルから GuestbookComments
、、Body
および 列をSubject
選択しCommentDate
、テーブルから 、HomepageUrl
、および Signature
列をUserProfiles
返HomeTown
し、 からaspnet_Users
を返しますUserName
。 また、クエリのSELECT
最後に "ORDER BY CommentDate DESC
" を追加して、最新の投稿が最初に返されるようにします。 これらの選択を行った後、クエリ ビルダー インターフェイスは図 18 のスクリーン ショットのようになります。
図 18: 構築されたクエリ JOIN
の GuestbookComments
、 UserProfiles
、および aspnet_Users
テーブル (フルサイズの画像を表示する をクリックします)
[OK] をクリックして [クエリ ビルダー] ウィンドウを閉じ、[カスタム ステートメントまたはストアド プロシージャの定義] 画面に戻ります。 [次へ] をクリックして [クエリのテスト] 画面に進み、[クエリのテスト] ボタンをクリックしてクエリ結果を表示できます。 準備ができたら、[完了] をクリックしてデータ ソースの構成ウィザードを完了します。
手順 2 でデータ ソースの構成ウィザードを完了すると、関連付けられている DetailsView コントロールの Fields
コレクションが更新され、 によって返される各列の BoundField が SelectCommand
含まれます。 ただし、ListView は変更されません。レイアウトを定義する必要があります。 ListView のレイアウトは、宣言型マークアップを使用するか、スマート タグの [ListView の構成] オプションから手動で構築できます。 私は通常、マークアップを手動で定義することを好みますが、最も自然な方法を使用します。
私はListViewコントロールに次 LayoutTemplate
の、 ItemTemplate
、および ItemSeparatorTemplate
を使用しました:
<asp:ListView ID="CommentList" runat="server" DataSourceID="CommentsDataSource">
<LayoutTemplate>
<span ID="itemPlaceholder" runat="server" />
<p>
<asp:DataPager ID="DataPager1" runat="server">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button"
ShowFirstPageButton="True"
ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</p>
</LayoutTemplate>
<ItemTemplate>
<h4>
<asp:Label ID="SubjectLabel" runat="server"
Text='<%# Eval("Subject") %>' />
</h4>
<asp:Label ID="BodyLabel" runat="server"
Text='<%# Eval("Body").ToString().Replace(Environment.NewLine, "<br />") %>' />
<p>
---<br />
<asp:Label ID="SignatureLabel" Font-Italic="true" runat="server"
Text='<%# Eval("Signature") %>' />
<br />
<br />
My Home Town:
<asp:Label ID="HomeTownLabel" runat="server"
Text='<%# Eval("HomeTown") %>' />
<br />
My Homepage:
<asp:HyperLink ID="HomepageUrlLink" runat="server"
NavigateUrl='<%# Eval("HomepageUrl") %>'
Text='<%# Eval("HomepageUrl") %>' />
</p>
<p align="center">
Posted by
<asp:Label ID="UserNameLabel" runat="server"
Text='<%# Eval("UserName") %>' />
on
<asp:Label ID="CommentDateLabel" runat="server"
Text='<%# Eval("CommentDate") %>' />
</p>
</ItemTemplate>
<ItemSeparatorTemplate>
<hr />
</ItemSeparatorTemplate>
</asp:ListView>
は LayoutTemplate
コントロールによって出力されるマークアップを定義し ItemTemplate
、 は SqlDataSource によって返される各項目をレンダリングします。 ItemTemplate
結果のマークアップは、 の コントロールにLayoutTemplate
itemPlaceholder
配置されます。 にitemPlaceholder
LayoutTemplate
加えて、 には DataPager コントロールが含まれており、ListView は 1 ページあたり 10 個のゲストブック コメント (既定) のみを表示するように制限され、ページング インターフェイスがレンダリングされます。
My では ItemTemplate
、各ゲストブック コメントの件名が、件名 <h4>
の下に本文が配置された要素に表示されます。 本文の表示に使用される構文は、databinding ステートメントによって返されるデータを Eval("Body")
受け取り、それを文字列に変換し、改行を 要素に <br />
置き換えます。 HTML では空白文字が無視されるため、コメントの送信時に入力された改行を表示するには、この変換が必要です。 ユーザーの署名は、本文の下に斜体で表示され、その後にユーザーのホーム タウン、ホーム ページへのリンク、コメントが作成された日時、コメントを残したユーザーのユーザー名が表示されます。
ブラウザーを使用してページを表示するには、少し時間を取ります。 手順 5 でゲストブックに追加したコメントがここに表示されます。
図 19: Guestbook.aspx
ゲストブックのコメントが表示されるようになりました (クリックするとフルサイズの画像が表示されます)
ゲストブックに新しいコメントを追加してみてください。 ボタンを PostCommentButton
クリックすると、ページはポストバックされ、コメントはデータベースに追加されますが、ListView コントロールは更新されず、新しいコメントが表示されます。 これは、次のいずれかの方法で修正できます。
- 新しいコメントをデータベースに
PostCommentButton
挿入した後に ListView コントロールの メソッドを呼び出すようにボタンClick
のDataBind()
イベント ハンドラーを更新する、または - ListView コントロールの プロパティを
EnableViewState
に設定しますFalse
。 この方法は、コントロールのビュー ステートを無効にすることで、すべてのポストバックの基になるデータに再バインドする必要があるために機能します。
このチュートリアルからダウンロードできるチュートリアル Web サイトは、両方の手法を示しています。 ListView コントロールの EnableViewState
プロパティ False
と、プログラムによって ListView にデータを再バインドするために必要なコードは、イベント ハンドラーに Click
存在しますが、コメントアウトされます。
注意
現在、 AdditionalUserInfo.aspx
このページでは、ユーザーがホーム タウン、ホームページ、署名の設定を表示および編集できます。 ログインしているユーザーのゲストブックのコメントを表示するように更新 AdditionalUserInfo.aspx
すると便利な場合があります。 つまり、ユーザーは、自分の情報を調べて変更するだけでなく、ページにアクセス AdditionalUserInfo.aspx
して、過去に行ったゲストブックのコメントを確認できます。 私はこれを興味のある読者のための演習として残します。
手順 6: CreateUserWizard コントロールをカスタマイズして、ホーム タウン、ホームページ、署名のインターフェイスを含める
ページで使用されるクエリではSELECT
、 をINNER JOIN
Guestbook.aspx
使用して、、UserProfiles
、および aspnet_Users
テーブルの間で関連レコードをGuestbookComments
結合します。 にレコードUserProfiles
がないユーザーがゲストブック コメントを作成した場合、 と に一致するレコードがある場合にのみレコードが返GuestbookComments
されるためINNER JOIN
、コメントは ListView にUserProfiles
aspnet_Users
表示されません。 手順 3 で説明したように、ユーザーがレコードを持っていない場合、ページで UserProfiles
設定を AdditionalUserInfo.aspx
表示または編集することはできません。
言うまでもなく、設計上の決定により、メンバーシップ システム内のすべてのユーザー アカウントがテーブル内に一致するレコードを UserProfiles
持つことが重要です。 必要なのは、CreateUserWizard を使用して新しいメンバーシップ ユーザー アカウントが作成されるたびに、対応するレコードを に追加 UserProfiles
することです。
「ユーザー アカウントの作成」チュートリアルで説明したように、新しいメンバーシップ ユーザー アカウントが作成された後、CreateUserWizard コントロールによってイベントがCreatedUser
発生します。 このイベントのイベント ハンドラーを作成し、作成したユーザーの UserId を取得してから、および Signature
列のUserProfiles
既定値を使用してレコードをHomeTown
HomepageUrl
テーブルに挿入できます。 さらに、追加の TextBox を含むように CreateUserWizard コントロールのインターフェイスをカスタマイズすることで、ユーザーにこれらの値の入力を求めることができます。
まず、イベント ハンドラーのテーブルに新しい行を UserProfiles
既定値で追加する方法を CreatedUser
見てみましょう。 その後、CreateUserWizard コントロールのユーザー インターフェイスをカスタマイズして、新しいユーザーのホーム タウン、ホーム ページ、署名を収集するための追加のフォーム フィールドを含める方法について説明します。
既定の行の追加UserProfiles
ユーザー アカウントの作成に関するチュートリアルでは、フォルダー内のページに CreatingUserAccounts.aspx
CreateUserWizard コントロールをMembership
追加しました。 CreateUserWizard コントロールがユーザー アカウントの作成時にテーブルにレコードを UserProfiles
追加するには、CreateUserWizard コントロールの機能を更新する必要があります。 これらの変更をページに CreatingUserAccounts.aspx
加えるのではなく、新しい CreateUserWizard コントロールをページに EnhancedCreateUserWizard.aspx
追加し、そこでこのチュートリアルの変更を加えてみましょう。
Visual Studio でページを EnhancedCreateUserWizard.aspx
開き、CreateUserWizard コントロールをツールボックスからページにドラッグします。 CreateUserWizard コントロールの ID
プロパティを に設定します NewUserWizard
。 「ユーザー アカウントの作成」チュートリアルで説明したように、CreateUserWizard の既定のユーザー インターフェイスは、訪問者に必要な情報を求めるメッセージを表示します。 この情報が提供されると、コントロールは内部的にメンバーシップ フレームワークに新しいユーザー アカウントを作成します。コードを 1 行記述する必要はありません。
CreateUserWizard コントロールは、ワークフロー中に多数のイベントを発生させます。 訪問者が要求情報を提供し、フォームを送信すると、CreateUserWizard コントロールは最初にイベントを CreatingUser
発生させます。 作成プロセス中に問題が発生すると CreateUserError
、イベント が発生します。ただし、ユーザーが正常に作成されると、 CreatedUser
イベント が発生します。 ユーザー アカウントの作成に関するチュートリアルでは、 イベントのCreatingUser
イベント ハンドラーを作成して、指定されたユーザー名に先頭または末尾のスペースが含まれていないことを確認し、ユーザー名がパスワードのどこにも表示されないようにしました。
作成したばかりのユーザーのテーブルに行を UserProfiles
追加するには、イベントのイベント ハンドラーを作成する CreatedUser
必要があります。 イベントが CreatedUser
発生した時点で、ユーザー アカウントは既にメンバーシップ フレームワークに作成されているため、アカウントの UserId 値を取得できます。
のイベントのイベント ハンドラーを NewUserWizard
作成し、次の CreatedUser
コードを追加します。
Protected Sub NewUserWizard_CreatedUser(ByVal sender As Object, ByVal e As System.EventArgs) Handles NewUserWizard.CreatedUser
' Get the UserId of the just-added user
Dim newUser As MembershipUser = Membership.GetUser(NewUserWizard.UserName)
Dim newUserId As Guid = CType(newUser.ProviderUserKey, Guid)
' Insert a new record into UserProfiles
Dim connectionString As String =
ConfigurationManager.ConnectionStrings("SecurityTutorialsConnectionString").ConnectionString
Dim insertSql As String = "INSERT INTO UserProfiles(UserId, HomeTown, HomepageUrl,
Signature) VALUES(@UserId, @HomeTown, @HomepageUrl, @Signature)"
Using myConnection As New SqlConnection(connectionString)
myConnection.Open()
Dim myCommand As New SqlCommand(insertSql, myConnection)
myCommand.Parameters.AddWithValue("@UserId", newUserId)
myCommand.Parameters.AddWithValue("@HomeTown", DBNull.Value)
myCommand.Parameters.AddWithValue("@HomepageUrl", DBNull.Value)
myCommand.Parameters.AddWithValue("@Signature", DBNull.Value)
myCommand.ExecuteNonQuery()
myConnection.Close()
End Using
End Sub
上記のコードは、追加したばかりのユーザー アカウントの UserId を取得することです。 これを行うには、 メソッドを使用して特定の Membership.GetUser(username)
ユーザーに関する情報を返し、 プロパティを ProviderUserKey
使用して UserId を取得します。 CreateUserWizard コントロールでユーザーが入力したユーザー名は、そのUserName
プロパティを使用して使用できます。
次に、接続文字列が からWeb.config
取得され、 ステートメントがINSERT
指定されます。 必要な ADO.NET オブジェクトがインスタンス化され、コマンドが実行されます。 このコードでは、および @Signature
の各パラメーターに@HomepageUrl
@HomeTown
インスタンスを割り当てますDBNull
。このパラメーターは、、HomepageUrl
、および Signature
フィールドのデータベースNULL
値をHomeTown
挿入する効果があります。
ブラウザーからページに EnhancedCreateUserWizard.aspx
アクセスし、新しいユーザー アカウントを作成します。 その後、Visual Studio に戻り、 テーブルと UserProfiles
テーブルの内容をaspnet_Users
調べます (図 12 で取り上げました)。 の新しいユーザー アカウントaspnet_Users
と、対応するUserProfiles
行 (、、HomepageUrl
および Signature
のHomeTown
値を含むNULL
) が表示されます。
図 20: 新しいユーザー アカウントと UserProfiles
レコードが追加されました (クリックするとフルサイズの画像が表示されます)
訪問者が新しいアカウント情報を入力し、[ユーザーの作成] ボタンをクリックすると、ユーザー アカウントが作成され、テーブルに行が UserProfiles
追加されます。 次に、CreateUserWizard に が CompleteWizardStep
表示され、成功メッセージと [続行] ボタンが表示されます。 [続行] ボタンをクリックするとポストバックが発生しますが、アクションは実行されません。ユーザーはページ上 EnhancedCreateUserWizard.aspx
でスタックしたままです。
CreateUserWizard コントロール ContinueDestinationPageUrl
の プロパティを使用して [続行] ボタンをクリックすると、ユーザーに送信する URL を指定できます。 プロパティを ContinueDestinationPageUrl
"~/Membership/AdditionalUserInfo.aspx" に設定します。 これにより、新しいユーザーは に移動 AdditionalUserInfo.aspx
し、そこで設定を表示および更新できます。
CreateUserWizard のインターフェイスをカスタマイズして、新しいユーザーのホーム タウン、ホーム ページ、署名の入力を求める
CreateUserWizard コントロールの既定のインターフェイスは、ユーザー名、パスワード、電子メールなどのコア ユーザー アカウント情報のみを収集する必要がある単純なアカウント作成シナリオに十分です。 しかし、アカウントの作成時に訪問者にホームタウン、ホームページ、署名の入力を求めたい場合はどうでしょうか。 サインアップ時に追加情報を収集するように CreateUserWizard コントロールのインターフェイスをカスタマイズできます。この情報は、イベント ハンドラーで CreatedUser
使用して、基になるデータベースに追加のレコードを挿入する場合があります。
CreateUserWizard コントロールは、ページ開発者が一連の順序付き を定義できるようにするコントロールである、ASP.NET ウィザード コントロールを拡張します WizardSteps
。 ウィザード コントロールは、アクティブなステップをレンダリングし、訪問者がこれらの手順を移動できるようにするナビゲーション インターフェイスを提供します。 ウィザード コントロールは、長いタスクをいくつかの短い手順に分割するのに最適です。 ウィザード コントロールの詳細については、「 ASP.NET 2.0 ウィザード コントロールを使用したステップ バイ ステップ ユーザー インターフェイスの作成」を参照してください。
CreateUserWizard コントロールの既定のマークアップは、 と CompleteWizardStep
の 2 つWizardSteps
CreateUserWizardStep
を定義します。
<asp:CreateUserWizard ID="NewUserWizard" runat="server"
ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
最初 WizardStep
の は CreateUserWizardStep
、ユーザー名、パスワード、電子メールなどを求めるインターフェイスをレンダリングします。 訪問者がこの情報を提供し、[ユーザーの作成] をクリックすると、 が表示 CompleteWizardStep
され、成功メッセージと [続行] ボタンが表示されます。
CreateUserWizard コントロールのインターフェイスをカスタマイズして、追加のフォーム フィールドを含めるには、次の操作を行います。
1 つ以上の新しい
WizardStep
を作成するは、追加のユーザー インターフェイス要素を格納します。 CreateUserWizard に新WizardStep
しいを追加するには、スマート タグから [追加/削除WizardStep
] リンクをクリックしてコレクション エディターをWizardStep
起動します。 そこから、ウィザードの手順を追加、削除、または並べ替えることができます。 これは、このチュートリアルで使用するアプローチです。を変換します。
CreateUserWizardStep
を編集可能にするWizardStep
。 これにより、 がCreateUserWizardStep
と一致するユーザー インターフェイスを定義する同等WizardStep
のマークアップにCreateUserWizardStep
置き換えられます。 をCreateUserWizardStep
にWizardStep
変換することで、コントロールの位置を変更したり、この手順にユーザー インターフェイス要素を追加したりできます。 またはCompleteWizardStep
をCreateUserWizardStep
編集可能にWizardStep
変換するには、コントロールのスマート タグから [ユーザー ステップの作成のカスタマイズ] または [完全なステップのカスタマイズ] リンクをクリックします。上記の 2 つのオプションを組み合わせて使用します。
注意すべき重要な点の 1 つは、CreateUserWizard コントロールが、その 内から [Create User]\(ユーザーの作成\) ボタンをクリックしたときに、ユーザー アカウントの作成プロセスを CreateUserWizardStep
実行することです。 の後CreateUserWizardStep
に 追加WizardStep
の が存在するかどうかは関係ありません。
CreateUserWizard コントロールにカスタム WizardStep
を追加して追加のユーザー入力を収集する場合は、 の前または後にカスタム WizardStep
を CreateUserWizardStep
配置できます。 が の CreateUserWizardStep
前にある場合は、カスタム WizardStep
から収集された追加のユーザー入力をイベント ハンドラーで CreatedUser
使用できます。 ただし、カスタムが表示される時点までにカスタムWizardStep
が表示される場合CreateUserWizardStep
は、新しいユーザー アカウントが既に作成されており、イベントが既にCreatedUser
発生WizardStep
しています。
図 21 は、 が の前に追加 WizardStep
されたときのワークフローを CreateUserWizardStep
示しています。 イベントが発生した時点CreatedUser
で追加のユーザー情報が収集されるため、これらの入力を取得し、ステートメントのパラメーター値 (ではなくDBNull.Value
) に使用INSERT
するようにイベント ハンドラーを更新CreatedUser
するだけで済みます。
図 21: CreateUserWizard ワークフローが の前CreateUserWizardStep
に追加WizardStep
されたとき (クリックするとフルサイズの画像が表示されます)
ただし、 の後CreateUserWizardStep
にカスタムWizardStep
を配置すると、ユーザーがホーム タウン、ホームページ、または署名に入る前に、ユーザー アカウントの作成プロセスが行われます。 このような場合は、図 22 に示すように、ユーザー アカウントの作成後に、この追加情報をデータベースに挿入する必要があります。
図 22: CreateUserWizard ワークフローの後CreateUserWizardStep
に追加WizardStep
が来たとき (クリックするとフルサイズの画像が表示されます)
図 22 に示すワークフローは、手順 2 が完了するまでテーブルへのレコードの UserProfiles
挿入を待機します。 ただし、手順 1 の後に訪問者がブラウザーを閉じると、ユーザー アカウントが作成された状態に達しましたが、 に UserProfiles
レコードは追加されませんでした。 回避策の 1 つは、イベント ハンドラーに または の既定値を含むNULL
レコードをCreatedUser
挿入UserProfiles
し (手順 1 の後に発生します)、手順 2 の完了後にこのレコードを更新することです。 これにより、ユーザーが途中で UserProfiles
登録プロセスを終了した場合でも、ユーザー アカウントのレコードが確実に追加されます。
このチュートリアルでは、 の後と の前CreateUserWizardStep
に発生する新しい WizardStep
をCompleteWizardStep
作成しましょう。 最初に WizardStep を設定し、構成してから、コードを見てみましょう。
CreateUserWizard コントロールのスマート タグから、[追加/削除WizardStep
] を選択すると、[コレクションのエディター] ダイアログが表示WizardStep
されます。 新 WizardStep
しい を追加し、 を ID
に UserSettings
設定し、その Title
を "Your Settings" に、その を StepType
に設定します Step
。 次に、図 23 に示すように、 CreateUserWizardStep
("新しいアカウントにサインアップ") の後と ("完了") の前 CompleteWizardStep
に来るように配置します。
図 23: CreateUserWizard コントロールに新規 WizardStep
を追加する (フルサイズの画像を表示する をクリックします)
[OK] をクリックして、[コレクションのWizardStep
エディター] ダイアログを閉じます。 新しい WizardStep
は、CreateUserWizard コントロールの更新された宣言型マークアップによって証明されます。
<asp:CreateUserWizard ID="NewUserWizard" runat="server"
ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:WizardStep runat="server" ID="UserSettings" StepType="Step"
Title="Your Settings">
</asp:WizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
新しい <asp:WizardStep>
要素をメモします。 ここでは、新しいユーザーのホーム タウン、ホームページ、署名を収集するためのユーザー インターフェイスを追加する必要があります。 このコンテンツは、宣言構文またはDesignerを使用して入力できます。 Designerを使用するには、[スマート タグ] のドロップダウン リストから [設定] ステップを選択して、Designerの手順を確認します。
注意
スマート タグのドロップダウン リストからステップを選択すると、開始ステップのインデックスを指定する CreateUserWizard コントロール ActiveStepIndex
の プロパティが更新されます。 そのため、このドロップダウン リストを使用してDesignerの [設定] ステップを編集する場合は、必ず "新しいアカウントにサインアップ" に戻して、ユーザーがページに初めてアクセスEnhancedCreateUserWizard.aspx
したときにこの手順が表示されるようにしてください。
、、および という名前HomeTown
HomepageUrl
の 3 つの TextBox コントロールを含む "設定" ステップ内にユーザー インターフェイスをSignature
作成します。 このインターフェイスを構築すると、CreateUserWizard の宣言型マークアップは次のようになります。
<asp:CreateUserWizard ID="NewUserWizard" runat="server"
ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:WizardStep runat="server" ID="UserSettings" StepType="Step"
Title="Your Settings">
<p>
<b>Home Town:</b><br />
<asp:TextBox ID="HomeTown" runat="server"></asp:TextBox>
</p>
<p>
<b>Homepage URL:</b><br />
<asp:TextBox ID="HomepageUrl" Columns="40" runat="server"></asp:TextBox>
</p>
<p>
<b>Signature:</b><br />
<asp:TextBox ID="Signature" TextMode="MultiLine" Width="95%"
Rows="5" runat="server"></asp:TextBox>
</p>
</asp:WizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
先に進み、ブラウザーからこのページにアクセスし、ホーム タウン、ホームページ、署名の値を指定して、新しいユーザー アカウントを作成します。 完了すると、 CreateUserWizardStep
ユーザー アカウントがメンバーシップ フレームワークに作成され、イベント ハンドラーが実行されます CreatedUser
。これにより、 に UserProfiles
新しい行が追加されますが、データベース NULL
値 HomeTown
は 、 HomepageUrl
、および Signature
になります。 ホーム タウン、ホームページ、署名に入力された値は使用されません。 結果は、および Signature
フィールドがまだ指定されていないレコードHomepageUrl
HomeTown
を持つUserProfiles
新しいユーザー アカウントです。
ユーザーが入力したホーム タウン、honepage、署名の値を取得し、適切なレコードを更新する "設定" ステップの後にコードを実行する必要があります UserProfiles
。 ユーザーがウィザード コントロールのステップ間を移動するたびに、ウィザードの ActiveStepChanged
イベント が発生します。 このイベントのイベント ハンドラーを作成し、"設定" ステップが UserProfiles
完了したらテーブルを更新できます。
CreateUserWizard のイベントのイベント ハンドラーを追加し、次の ActiveStepChanged
コードを追加します。
Protected Sub NewUserWizard_ActiveStepChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles NewUserWizard.ActiveStepChanged
' Have we JUST reached the Complete step?
If NewUserWizard.ActiveStep.Title = "Complete" Then
Dim UserSettings As WizardStep = CType(NewUserWizard.FindControl("UserSettings"),WizardStep)
' Programmatically reference the TextBox controls
Dim HomeTown As TextBox = CType(UserSettings.FindControl("HomeTown"), TextBox)
Dim HomepageUrl As TextBox = CType(UserSettings.FindControl("HomepageUrl"), TextBox)
Dim Signature As TextBox = CType(UserSettings.FindControl("Signature"), TextBox)
' Update the UserProfiles record for this user
' Get the UserId of the just-added user
Dim newUser As MembershipUser = Membership.GetUser(NewUserWizard.UserName)
Dim newUserId As Guid = CType(newUser.ProviderUserKey, Guid)
' Insert a new record into UserProfiles
Dim connectionString As String = ConfigurationManager.ConnectionStrings("SecurityTutorialsConnectionString").ConnectionString
Dim updateSql As String = "UPDATE UserProfiles SET HomeTown = @HomeTown, HomepageUrl
= @HomepageUrl, Signature = @Signature WHERE UserId = @UserId"
Using myConnection As New SqlConnection(connectionString)
myConnection.Open()
Dim myCommand As New SqlCommand(updateSql, myConnection)
myCommand.Parameters.AddWithValue("@HomeTown", HomeTown.Text.Trim())
myCommand.Parameters.AddWithValue("@HomepageUrl", HomepageUrl.Text.Trim())
myCommand.Parameters.AddWithValue("@Signature", Signature.Text.Trim())
myCommand.Parameters.AddWithValue("@UserId", newUserId)
myCommand.ExecuteNonQuery()
myConnection.Close()
End Using
End If
End Sub
上記のコードは、"完了" ステップに達したばかりのかどうかを判断することから始まります。 「設定」ステップの直後に「完了」ステップが行われるので、訪問者が「完了」ステップに達すると、彼女はちょうど「設定」ステップを完了したことを意味します。
このような場合は、 内 UserSettings WizardStep
の TextBox コントロールをプログラムで参照する必要があります。 これは、最初に メソッドを FindControl
使用して プログラムで を参照 UserSettings WizardStep
し、 内から TextBox を参照することで実現されます WizardStep
。 TextBoxes が参照されたら、 ステートメントを実行 UPDATE
する準備ができました。 ステートメントにはUPDATE
、イベント ハンドラーの ステートメントCreatedUser
と同じ数のパラメーターINSERT
がありますが、ここでは、ユーザーによって提供されるホーム タウン、ホームページ、および署名の値を使用します。
このイベント ハンドラーを配置した状態で、ブラウザーからページに EnhancedCreateUserWizard.aspx
アクセスし、ホーム タウン、ホームページ、署名の値を指定する新しいユーザー アカウントを作成します。 新しいアカウントを作成した後、ページに AdditionalUserInfo.aspx
リダイレクトされます。ここで、入力したホーム タウン、ホームページ、署名情報が表示されます。
注意
現在、当社のウェブサイトには、訪問者が新しいアカウントを作成できる2つのページがあります: CreatingUserAccounts.aspx
と EnhancedCreateUserWizard.aspx
。 Web サイトマップとログイン ページはページを CreatingUserAccounts.aspx
ポイントしますが CreatingUserAccounts.aspx
、このページではユーザーにホーム タウン、ホームページ、署名情報の入力を求めるメッセージは表示されず、対応する行は に UserProfiles
追加されません。 そのため、この機能を提供するようにページをCreatingUserAccounts.aspx
更新するか、 ではなくCreatingUserAccounts.aspx
、サイトマップとログイン ページを参照EnhancedCreateUserWizard.aspx
するように更新します。 後者のオプションを選択する場合は、匿名ユーザーが Membership
ページにアクセスできるように、フォルダーの Web.config
ファイルを EnhancedCreateUserWizard.aspx
必ず更新してください。
まとめ
このチュートリアルでは、メンバーシップ フレームワーク内のユーザー アカウントに関連するデータをモデリングする手法について説明しました。 特に、ユーザー アカウントと一対多リレーションシップを共有するモデリング エンティティと、一対一リレーションシップを共有するデータについて説明しました。 さらに、この関連情報を表示、挿入、更新する方法を確認しました。SqlDataSource コントロールを使用する例もあれば、ADO.NET コードを使用する例もあります。
このチュートリアルでは、ユーザー アカウントの確認を完了します。 次のチュートリアルから始めて、ロールに注目します。 次のいくつかのチュートリアルでは、Roles フレームワークについて説明します。新しいロールを作成する方法、ユーザーにロールを割り当てる方法、ユーザーが属するロールを決定する方法、ロールベースの承認を適用する方法について説明します。
プログラミングに満足!
もっと読む
このチュートリアルで説明するトピックの詳細については、次のリソースを参照してください。
- ASP.NET 2.0 でのデータへのアクセスと更新
- ASP.NET 2.0 ウィザード コントロール
- ASP.NET 2.0 ウィザード コントロールを使用したステップ バイ ステップ ユーザー インターフェイスの作成
- カスタム DataSource コントロール パラメーターの作成
- CreateUserWizard コントロールのカスタマイズ
- DetailsView コントロール クイック スタート
- ListView コントロールを使用したデータの表示
- ASP.NET 2.0 での検証コントロールの解剖
- データの挿入と削除の編集
- ASP.NET でのフォームの検証
- カスタム ユーザー登録情報の収集
- ASP.NET 2.0 のプロファイル
- asp:ListView コントロール
- [ユーザー プロファイル] クイック スタート
著者について
複数の 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をドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示