追加のユーザー情報を格納する (C#)
注意
この記事が作成されて以来、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 データベースに格納する sthat が付属しています。 実際、データベースには(aspnet_Profile
)によってSqlProfileProvider
使用されているテーブルが既に含まれています。これは、アプリケーション サービスを「Creating the Membership Schema in 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 void UserProfileDataSource_Selecting(object sender,
SqlDataSourceSelectingEventArgs e)
{
// Get a reference to the currently logged on user
MembershipUser currentUser = Membership.GetUser();
// Determine the currently logged on user's UserId value
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
// Assign the currently logged on user's UserId to the @UserId parameter
e.Command.Parameters["@UserId"].Value = currentUserId;
}
上記のコードは、まず、 クラスGetUser
の メソッドを呼び出して、現在ログオンしているユーザーへの参照をMembership
取得します。 これにより、 ProviderUserKey
プロパティに がMembershipUser
含まれる オブジェクトが返されますUserId
。 その UserId
後、値は SqlDataSource @UserId
のパラメーターに割り当てられます。
注意
メソッドは Membership.GetUser()
、現在ログオンしているユーザーに関する情報を返します。 匿名ユーザーがページにアクセスしている場合は、 の null
値が返されます。 このような場合、 プロパティを NullReferenceException
読み取ろうとすると、次のコード行で が ProviderUserKey
発生します。 もちろん、認証されたユーザーのみがこのフォルダー内の AdditionalUserInfo.aspx
ASP.NET リソースにアクセスできるように、前のチュートリアルで URL 承認を構成したため、ページ内の値を返すnull
心配Membership.GetUser()
はありません。 匿名アクセスが許可されているページで現在ログオンしているユーザーに関する情報にアクセスする必要がある場合は、プロパティを参照する前に、メソッドからGetUser()
非null MembershipUser
オブジェクトが返されることをチェックしてください。
ブラウザーを使用してページに 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
戻り、Bruce としてログインします。 図 13 に示すように、Bruce の設定が表示されます。
図 13: 現在アクセスしているユーザーの設定が表示されます (クリックするとフルサイズの画像が表示されます)
注意
次に進み、各メンバーシップ ユーザーのテーブルにレコードを UserProfiles
手動で追加します。 手順 6 では、CreateUserWizard コントロールをカスタマイズして、新しいユーザー アカウントの作成時にテーブルに新しい行を自動的に追加する UserProfiles
方法について説明します。
手順 3: ユーザーがホーム タウン、ホームページ、署名を編集できるようにする
この時点で、現在ログインしているユーザーはホーム タウン、ホームページ、署名の設定を表示できますが、まだ変更することはできません。 データを編集できるように DetailsView コントロールを更新してみましょう。
最初に行う必要があるのは、SqlDataSource に を追加 UpdateCommand
し、実行する UPDATE
ステートメントとそれに対応するパラメーターを指定することです。 [SqlDataSource] を選択し、プロパティ ウィンドウから UpdateQuery プロパティの横にある省略記号をクリックして、[コマンド エディターとパラメーター エディター] ダイアログ ボックスを表示します。 テキスト ボックスに次 UPDATE
のステートメントを入力します。
UPDATE UserProfiles SET
HomeTown = @HomeTown,
HomepageUrl = @HomepageUrl,
Signature = @Signature
WHERE UserId = @UserId
次に、[パラメーターの更新] ボタンをクリックします。これにより、 ステートメント内の各パラメーターのパラメーターが SqlDataSource コントロールの UpdateParameters
コレクションに UPDATE
作成されます。 すべてのパラメーターのソースを [なし] に設定したまま、[OK] ボタンをクリックしてダイアログ ボックスを完了します。
図 14: SqlDataSource の UpdateCommand
と UpdateParameters
を指定します (クリックするとフルサイズの画像が表示されます)
SqlDataSource コントロールに追加されたため、DetailsView コントロールで編集をサポートできるようになりました。 DetailsView のスマート タグから、[編集を有効にする] チェックボックスをチェックします。 これにより、コントロールのコレクションに Fields
CommandField が追加され、そのプロパティが ShowEditButton
True に設定されます。 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 の上に Label コントロールを追加します。 を 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 void UserProfile_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
{
SettingsUpdatedMessage.Visible = true;
}
ブラウザーからページに 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
。 この名前空間をページの分離コード クラス (つまり) using System.Data.SqlClient;
にインポートする必要がある場合があります。
のイベントのイベント ハンドラーを PostCommentButton
作成し、次の Click
コードを追加します。
protected void PostCommentButton_Click(object sender, EventArgs e)
{
if (!Page.IsValid)
return;
// Determine the currently logged on user's UserId
MembershipUser currentUser = Membership.GetUser();
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
// Insert a new record into GuestbookComments
string connectionString =
ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
string insertSql = "INSERT INTO GuestbookComments(Subject, Body, UserId) VALUES(@Subject,
@Body, @UserId)";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = 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();
}
// "Reset" the Subject and Body TextBoxes
Subject.Text = string.Empty;
Body.Text = string.Empty;
}
イベント ハンドラーは Click
、まず、ユーザーが指定したデータが有効であることを確認します。 そうでない場合、イベント ハンドラーはレコードを挿入する前に終了します。 指定されたデータが有効であると仮定すると、現在ログオンしているユーザーの UserId
値が取得され、ローカル変数に currentUserId
格納されます。 レコードを にGuestbookComments
挿入するときに値をUserId
指定する必要があるため、この値が必要です。
その後、データベースの接続文字列が SecurityTutorials
から Web.config
取得され、 INSERT
SQL ステートメントが指定されます。 SqlConnection
その後、オブジェクトが作成されて開かれます。 次に SqlCommand
、オブジェクトが構築され、クエリで使用されるパラメーターの値が INSERT
割り当てられます。 INSERT
その後、 ステートメントが実行され、接続が閉じられます。 イベント ハンドラーの最後に、 Subject
プロパティと Body
TextBoxes プロパティ Text
がクリアされ、ポストバック全体でユーザーの値が永続化されません。
先に進み、ブラウザーでこのページをテストします。 このページはフォルダー内にありますので Membership
、匿名の訪問者はアクセスできません。 そのため、最初にログオンする必要があります (まだログオンしていない場合)。 および Body
TextBoxes に値をSubject
入力し、ボタンをPostCommentButton
クリックします。 これにより、新しいレコードが に GuestbookComments
追加されます。 ポストバック時に、指定した件名と本文がテキスト ボックスからワイプされます。
ボタンを PostCommentButton
クリックした後、コメントがゲストブックに追加されたという視覚的なフィードバックはありません。 手順 5 で行う既存のゲストブック コメントを表示するには、このページを更新する必要があります。 これを行うと、追加されたコメントがコメントの一覧に表示され、適切な視覚的フィードバックが提供されます。 ここでは、テーブルの内容を調べることで、ゲストブックの GuestbookComments
コメントが保存されたことを確認します。
図 17 は、2 つのコメントが残された後の GuestbookComments
テーブルの内容を示しています。
図 17: テーブルにゲストブックのコメントを GuestbookComments
表示できます (フルサイズの画像を表示する をクリックします)
注意
ユーザーが潜在的に危険なマークアップ (HTML など) を含むゲストブック コメントを挿入しようとすると、ASP.NET は を HttpRequestValidationException
スローします。 この例外の詳細、スローされる理由、およびユーザーが危険な可能性のある値を送信できるようにする方法については、「 検証の要求に関するホワイトペーパー」を参照してください。
手順 5: 既存のゲストブックコメントを一覧表示する
コメントを残すだけでなく、ページにアクセスする Guestbook.aspx
ユーザーもゲストブックの既存のコメントを表示できる必要があります。 これを実現するには、ページの下部に という名前 CommentList
の ListView コントロールを追加します。
注意
ListView コントロールは、バージョン 3.5 ASP.NET 初めて使用できます。 これは、非常にカスタマイズ可能で柔軟なレイアウトで項目の一覧を表示するように設計されています。ただし、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 つのテーブルすべてがデザイン サーフェイスに追加されます。 、、および aspnet_Users
テーブルの間GuestbookComments
UserProfiles
には外部キー制約があるため、クエリ ビルダーによってこれらのテーブルが自動的JOIN
に作成されます。
残っているのは、返す列を指定することです。 GuestbookComments
テーブルから 、Body
、および 列をSubject
選択しCommentDate
、テーブルから 、HomepageUrl
、および Signature
列をUserProfiles
返HomeTown
し、 からaspnet_Users
を返しますUserName
。 また、クエリのSELECT
最後に "ORDER BY CommentDate DESC
" を追加して、最新の投稿が最初に返されるようにします。 これらの選択を行った後、Query Builder インターフェイスは図 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
結果のマークアップは、 の itemPlaceholder
コントロールにLayoutTemplate
配置されます。 に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
ページで使用されるクエリでは、 Guestbook.aspx
をINNER JOIN
使用して、、UserProfiles
、および の各テーブル間で関連レコードをGuestbookComments
aspnet_Users
結合します。 にレコード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 の既定のユーザー インターフェイスは、訪問者に必要な情報を求めます。 この情報が提供されると、コントロールは内部的に Membership フレームワークに新しいユーザー アカウントを作成します。コードを 1 行記述する必要はありません。
CreateUserWizard コントロールは、ワークフロー中に多数のイベントを発生させます。 訪問者が要求情報を提供し、フォームを送信すると、CreateUserWizard コントロールは最初にその CreatingUser
イベントを発生させます。 作成プロセス中に問題が発生した CreateUserError
場合は、イベント が発生します。ただし、ユーザーが正常に作成されると、 CreatedUser
イベント が発生します。 ユーザー アカウントの作成に関するチュートリアルでは、 イベントのCreatingUser
イベント ハンドラーを作成して、指定されたユーザー名に先頭または末尾のスペースが含まれていないことを確認し、ユーザー名がパスワード内のどこにも表示されないようにしました。
作成したばかりのユーザーのテーブルに行を UserProfiles
追加するには、イベントのイベント ハンドラーを作成する CreatedUser
必要があります。 イベントが CreatedUser
発生する頃には、メンバーシップ フレームワークでユーザー アカウントが既に作成されているため、アカウントの UserId 値を取得できます。
の イベントのイベント ハンドラーをNewUserWizard
CreatedUser
作成し、次のコードを追加します。
protected void NewUserWizard_CreatedUser(object sender, EventArgs e)
{
// Get the UserId of the just-added user
MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
Guid newUserId = (Guid)newUser.ProviderUserKey;
// Insert a new record into UserProfiles
string connectionString =
ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
string insertSql = "INSERT INTO UserProfiles(UserId, HomeTown, HomepageUrl,
Signature) VALUES(@UserId, @HomeTown, @HomepageUrl, @Signature)";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = 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();
}
}
上記のコードは、追加したばかりのユーザー アカウントの 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
しいを追加するには、スマート タグから [追加/削除WizardSteps
] リンクをクリックしてコレクション エディターをWizardStep
起動します。 そこから、ウィザードの手順を追加、削除、または並べ替えることができます。 これは、このチュートリアルで使用するアプローチです。を変換する
CreateUserWizardStep
を編集可能にするWizardStep
. これにより、 がCreateUserWizardStep
に一致するWizardStep
ユーザー インターフェイスを定義する同等のマークアップにCreateUserWizardStep
置き換えられます。 をCreateUserWizardStep
にWizardStep
変換することで、コントロールの位置を変更したり、この手順にユーザー インターフェイス要素を追加したりできます。 またはCompleteWizardStep
をCreateUserWizardStep
編集可能にWizardStep
変換するには、コントロールのスマート タグから [ユーザー ステップの作成のカスタマイズ] または [完全なステップのカスタマイズ] リンクをクリックします。上記の 2 つのオプションを組み合わせて使用します。
重要な点の 1 つは、CreateUserWizard コントロールが、ユーザーの作成ボタンが 内からクリックされたときに、ユーザー アカウントの作成プロセスを CreateUserWizardStep
実行することです。 の後CreateUserWizardStep
に が追加WizardStep
されているかどうかは関係ありません。
追加のユーザー入力を収集するために CreateUserWizard コントロールにカスタム WizardStep
を追加する場合は、 の前または後にカスタム WizardStep
を CreateUserWizardStep
配置できます。 が の前にある CreateUserWizardStep
場合は、カスタム WizardStep
から収集された追加のユーザー入力をイベント ハンドラーで CreatedUser
使用できます。 ただし、カスタムが表示される時点までにカスタムWizardStep
が表示される場合CreateUserWizardStep
は、新しいユーザー アカウントが既に作成され、イベントが既にCreatedUser
発生WizardStep
しています。
図 21 は、追加 WizardStep
された が の前にあるワークフローを CreateUserWizardStep
示しています。 イベントが発生するたびにCreatedUser
追加のユーザー情報が収集されるため、イベント ハンドラーを更新CreatedUser
してこれらの入力を取得し、ステートメントのパラメーター値 (ではなくDBNull.Value
) に使用INSERT
するだけで済みます。
図 21: 追加 WizardStep
の が の前 CreateUserWizardStep
にある場合の CreateUserWizard ワークフロー (フルサイズの画像を表示する をクリックします)
ただし、 の後CreateUserWizardStep
にカスタムWizardStep
を配置すると、ユーザーがホーム タウン、ホームページ、または署名に入る機会が生じる前に、ユーザー アカウントの作成プロセスが行われます。 このような場合は、図 22 に示すように、ユーザー アカウントの作成後に、この追加情報をデータベースに挿入する必要があります。
図 22: 追加 WizardStep
のが の後 CreateUserWizardStep
に来たときの CreateUserWizard ワークフロー (フルサイズの画像を表示する をクリックします)
図 22 に示すワークフローは、手順 2 が完了するまで、テーブルへのレコードの UserProfiles
挿入を待機します。 ただし、手順 1 の後に訪問者がブラウザーを閉じると、ユーザー アカウントが作成された状態に達しましたが、 に UserProfiles
レコードは追加されませんでした。 回避策の 1 つは、イベント ハンドラーにCreatedUser
または既定値が挿入されたレコード NULL
(手順 1 の後にUserProfiles
発生) を持ち、手順 2 の完了後にこのレコードを更新することです。 これにより、ユーザーが途中で UserProfiles
登録プロセスを終了した場合でも、ユーザー アカウントに対してレコードが追加されます。
このチュートリアルでは、 の後で、 の前CreateUserWizardStep
に発生する新しい WizardStep
をCompleteWizardStep
作成してみましょう。 最初に WizardStep を配置して構成してから、コードを見てみましょう。
CreateUserWizard コントロールのスマート タグから、[追加/削除 WizardStep
] を選択すると、[コレクション エディター] ダイアログが WizardStep
表示されます。 新 WizardStep
しい を追加し、 を ID
に UserSettings
設定し、そのを Title
"Your Settings" に、その を StepType
に設定します Step
。 次に、図 23 に示すように、("新しいアカウントにサインアップ") の後 CreateUserWizardStep
、("Complete") の前 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
したときにこの手順が表示されるように、必ず "新しいアカウントにサインアップする" に設定してください。
、、および Signature
という名前HomeTown
HomepageUrl
の 3 つの TextBox コントロールを含む "設定" ステップ内にユーザー インターフェイスを作成します。 このインターフェイスを構築すると、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
ユーザー アカウントが Membership フレームワークに作成され、イベント ハンドラーが実行され CreatedUser
、 に UserProfiles
新しい行が追加されますが、データベース NULL
値 HomeTown
は 、 HomepageUrl
、および Signature
になります。 ホーム タウン、ホームページ、署名に入力された値は使用されません。 結果は、および Signature
フィールドがまだ指定されていないレコードHomepageUrl
HomeTown
を持つUserProfiles
新しいユーザー アカウントです。
ホーム タウン、honepage、およびユーザーが入力した署名値を受け取り、適切なレコードを更新する "設定" ステップの後にコードを実行する必要があります UserProfiles
。 ユーザーがウィザード コントロールのステップ間を移動するたびに、ウィザードの ActiveStepChanged
イベント が発生します。 このイベントのイベント ハンドラーを作成し、"設定" ステップが UserProfiles
完了したらテーブルを更新できます。
CreateUserWizard のイベントのイベント ハンドラーを追加し、次の ActiveStepChanged
コードを追加します。
protected void NewUserWizard_ActiveStepChanged(object sender, EventArgs e)
{
// Have we JUST reached the Complete step?
if (NewUserWizard.ActiveStep.Title == "Complete")
{
WizardStep UserSettings = NewUserWizard.FindControl("UserSettings") as
WizardStep;
// Programmatically reference the TextBox controls
TextBox HomeTown = UserSettings.FindControl("HomeTown") as TextBox;
TextBox HomepageUrl = UserSettings.FindControl("HomepageUrl") as TextBox;
TextBox Signature = UserSettings.FindControl("Signature") as TextBox;
// Update the UserProfiles record for this user
// Get the UserId of the just-added user
MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
Guid newUserId = (Guid)newUser.ProviderUserKey;
// Insert a new record into UserProfiles
string connectionString =
ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
string updateSql = "UPDATE UserProfiles SET HomeTown = @HomeTown, HomepageUrl
= @HomepageUrl, Signature = @Signature WHERE UserId = @UserId";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = 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();
}
}
}
上記のコードは、"完了" ステップに達したばかりのかどうかを判断することから始めます。 "設定" ステップの直後に "完了" ステップが行われるので、訪問者が "完了" ステップに達すると、"設定" ステップが完了したことを意味します。
このような場合は、 内 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
必ず更新してください。
まとめ
このチュートリアルでは、Membership フレームワーク内のユーザー アカウントに関連するデータをモデリングする手法について説明しました。 特に、ユーザー アカウントと一対多リレーションシップを共有するモデリング エンティティと、1 対 1 のリレーションシップを共有するデータについて説明しました。 さらに、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 は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 Scott は、 または mitchell@4guysfromrolla.com のブログから http://ScottOnWriting.NETアクセスできます。
特別な感謝...
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 に mitchell@4GuysFromRolla.com行をドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示