Сохранение дополнительных сведений о пользователе (VB)Storing Additional User Information (VB)

по Скотт Митчеллby Scott Mitchell

Скачать код или скачать PDFDownload Code or Download PDF

В этом учебнике мы будем отвечать на этот вопрос, создав очень элементарное приложение гостевой книги.In this tutorial we will answer this question by building a very rudimentary guestbook application. При этом будут рассмотрены различные варианты моделирования сведений о пользователях в базе данных, а затем показано, как связать эти данные с учетными записями пользователей, созданными платформой членства.In doing so, we will look at different options for modeling user information in a database, and then see how to associate this data with the user accounts created by the Membership framework.

ВведениеIntroduction

Сценарии. Инфраструктура членства NET предлагает гибкий интерфейс для управления пользователями.ASP.NET's Membership framework offers a flexible interface for managing users. API членства включает методы для проверки учетных данных, получения сведений о вошедшем в систему пользователе, создания новой учетной записи пользователя и удаления учетной записи пользователя в других.The Membership API includes methods for validating credentials, retrieving information about the currently logged on user, creating a new user account, and deleting a user account, among others. Каждая учетная запись пользователя в инфраструктуре членства содержит только свойства, необходимые для проверки учетных данных и выполнения необходимых задач, связанных с учетной записью пользователя.Each user account in the Membership framework contains only the properties needed for validating credentials and performing essential user account-related tasks. Это свидетельствует о методах и свойствах классаMembershipUser, который моделирует учетную запись пользователя в инфраструктуре членства.This is evidenced by the methods and properties of the MembershipUser class, which models a user account in the Membership framework. Этот класс имеет такие свойства, как UserName, Emailи IsLockedOut, и такие методы, как GetPassword и UnlockUser.This class has properties like UserName, Email, and IsLockedOut, and methods like GetPassword and UnlockUser.

Часто приложениям необходимо хранить дополнительные сведения о пользователе, не включенные в платформу членства.Oftentimes, applications need to store additional user information not included in the Membership framework. Например, в Интернет-магазине может потребоваться предоставить каждому пользователю возможность хранить адреса доставки и выставления счетов, платежные данные, параметры доставки и номер телефона.For example, an online retailer might need to let each user store her shipping and billing addresses, payment information, delivery preferences, and contact phone number. Кроме того, каждый заказ в системе связан с определенной учетной записью пользователя.Furthermore, each order in the system is associated with a particular user account.

Класс MembershipUser не включает такие свойства, как PhoneNumber или DeliveryPreferences или PastOrders.The MembershipUser class does not include properties like PhoneNumber or DeliveryPreferences or PastOrders. Итак, как мы относимся к информации о пользователях, необходимой приложению, и они интегрируются с платформой членства?So how do we track the user information needed by the application and have it integrate with the Membership framework? В этом учебнике мы будем отвечать на этот вопрос, создав очень элементарное приложение гостевой книги.In this tutorial we will answer this question by building a very rudimentary guestbook application. При этом будут рассмотрены различные варианты моделирования сведений о пользователях в базе данных, а затем показано, как связать эти данные с учетными записями пользователей, созданными платформой членства.In doing so, we will look at different options for modeling user information in a database, and then see how to associate this data with the user accounts created by the Membership framework. Приступим.Let's get started!

Шаг 1. Создание модели данных приложения гостевой книгиStep 1: Creating the Guestbook Application's Data Model

Существует множество методов, которые можно использовать для сбора сведений о пользователях в базе данных и связывания их с учетными записями пользователей, созданными платформой членства.There are a variety of techniques that can be employed to capture user information in a database and associate it with the user accounts created by the Membership framework. Чтобы продемонстрировать эти методы, необходимо расширить веб-приложение Tutorial, чтобы оно захватывает некоторые данные, связанные с пользователем.In order to illustrate these techniques, we will need to augment the tutorial web application so that it captures some sort of user-related data. (В настоящее время модель данных приложения содержит только таблицы служб приложений, необходимые для SqlMembershipProvider.)(Currently, the application's data model contains only the application services tables needed by the SqlMembershipProvider.)

Давайте создадим очень простое приложение гостевой книги, где пользователь, прошедший проверку подлинности, может покинуть комментарий.Let's create a very simple guestbook application where an authenticated user can leave a comment. Помимо хранения комментариев гостевой книги, давайте разберем каждому пользователю хранение своего домашнего города, домашней страницы и подписи.In addition to storing guestbook comments, let's allow each user to store his home town, homepage, and signature. Если этот параметр указан, в каждом сообщении, которое он оставил в гостевой книге, будут отображаться домашние город, Домашняя страница и подпись пользователя.If provided, the user's home town, homepage, and signature will appear on each message he has left in the guestbook.

Добавление таблицыGuestbookCommentsAdding theGuestbookCommentsTable

Чтобы записать комментарии к гостевой книге, необходимо создать таблицу базы данных с именем GuestbookComments со столбцами, такими как CommentId, Subject, Bodyи CommentDate.In order to capture the guestbook comments, we need to create a database table named GuestbookComments that has columns like CommentId, Subject, Body, and CommentDate. Также необходимо, чтобы каждая запись в таблице GuestbookComments ссылалась на пользователя, который оставил комментарий.We also need to have each record in the GuestbookComments table reference the user who left the comment.

Чтобы добавить эту таблицу в базу данных, перейдите к обозреватель базы данных в Visual Studio и выполните детализацию для базы данных SecurityTutorials.To add this table to our database, go to the Database Explorer in Visual Studio and drill down into the SecurityTutorials database. Щелкните правой кнопкой мыши папку таблицы и выберите команду Добавить новую таблицу.Right-click on the Tables folder and choose Add New Table. Откроется интерфейс, позволяющий определить столбцы для новой таблицы.This brings up an interface that allows us to define the columns for the new table.

добавить новую таблицу в базу данных СекурититуториалсAdd a New Table to the SecurityTutorials Database

Рис. 1. Добавление новой таблицы в базу данных SecurityTutorials (щелкните, чтобы просмотреть изображение с полным размером)Figure 1: Add a New Table to the SecurityTutorials Database (Click to view full-size image)

Затем определите столбцы GuestbookComments.Next, define the GuestbookComments's columns. Сначала добавьте столбец с именем CommentId типа uniqueidentifier.Start by adding a column named CommentId of type uniqueidentifier. Этот столбец уникально идентифицирует каждый комментарий в гостевой книге, поэтому не следует NULL s и пометить его как первичный ключ таблицы.This column will uniquely identify each comment in the guestbook, so disallow NULL s and mark it as the table's primary key. Вместо того чтобы указывать значение для поля CommentId в каждой INSERT, можно указать, что новое значение uniqueidentifier должно автоматически создаваться для этого поля в INSERT, задав для столбца значение по умолчанию NEWID().Rather than providing a value for the CommentId field on each INSERT, we can indicate that a new uniqueidentifier value should be automatically generated for this field on INSERT by setting the column's default value to NEWID(). После добавления первого поля, помечая его как первичный ключ, и настройки его значения по умолчанию экран должен выглядеть примерно так, как на снимке экрана, показанном на рис. 2.After adding this first field, marking it as the primary key, and settings its default value, your screen should look similar to the screen shot shown in Figure 2.

добавить первичный столбец с именем КомментидAdd a Primary Column Named CommentId

Рис. 2. Добавление первичного столбца с именем CommentId (щелкните, чтобы просмотреть изображение с полным размером)Figure 2: Add a Primary Column Named CommentId (Click to view full-size image)

Затем добавьте столбец с именем Subject типа nvarchar(50) и столбец с именем Body типа nvarchar(MAX), который запрещает NULL s в обоих столбцах.Next, add a column named Subject of type nvarchar(50) and a column named Body of type nvarchar(MAX), disallowing NULL s in both columns. После этого добавьте столбец с именем CommentDate типа datetime.Following that, add a column named CommentDate of type datetime. Запретите NULL s и задайте для столбца CommentDate значение по умолчанию getdate().Disallow NULL s and set the CommentDate column's default value to getdate().

Остается только добавить столбец, связывающий учетную запись пользователя с каждым комментарием гостевой книги.All that remains is to add a column that associates a user account with each guestbook comment. Один из вариантов — добавить столбец с именем UserName типа nvarchar(256).One option would be to add a column named UserName of type nvarchar(256). Это подходящий вариант при использовании поставщика членства, отличного от SqlMembershipProvider.This is a suitable choice when using a Membership provider other than the SqlMembershipProvider. Но при использовании SqlMembershipProvider, как описано в этой серии руководств, столбец UserName в таблице aspnet_Users не обязательно должен быть уникальным.But when using the SqlMembershipProvider, as we are in this tutorial series, the UserName column in the aspnet_Users table is not guaranteed to be unique. Первичный ключ aspnet_Usersной таблицы UserId и имеет тип uniqueidentifier.The aspnet_Users table's primary key is UserId and is of type uniqueidentifier. Таким образом, GuestbookComments таблице требуется столбец с именем UserId типа uniqueidentifier (запрещенные значения NULL).Therefore, the GuestbookComments table needs a column named UserId of type uniqueidentifier (disallowing NULL values). Добавьте этот столбец.Go ahead and add this column.

Note

Как мы обсуждали в руководстве Создание схемы членства в SQL Server , платформа членства разработана так, чтобы несколько веб-приложений с разными учетными записями пользователей совместно использовать одно и то же хранилище пользователей.As we discussed in the Creating the Membership Schema in SQL Server tutorial, the Membership framework is designed to enable multiple web applications with different user accounts to share the same user store. Это достигается путем секционирования учетных записей пользователей в разные приложения.It does this by partitioning user accounts into different applications. И хотя каждое имя пользователя гарантированно уникально в пределах приложения, одно и то же имя пользователя может использоваться в разных приложениях, использующих одно хранилище пользователей.And while each username is guaranteed to be unique within an application, the same username may be used in different applications using the same user store. В таблице aspnet_Users в полях UserName и ApplicationId имеется составное ограничение UNIQUE, но не одно в поле UserName.There is a composite UNIQUE constraint in the aspnet_Users table on the UserName and ApplicationId fields, but not one on just the UserName field. Следовательно, в таблице ASPNET_Users можно иметь две (или более) записи с одинаковым значением UserName.Consequently, it is possible for the aspnet_Users table to have two (or more) records with the same UserName value. Однако существует ограничение UNIQUE для поля UserId таблицы aspnet_Users (поскольку оно является первичным ключом).There is, however, a UNIQUE constraint on the aspnet_Users table's UserId field (since it is the primary key). Ограничение UNIQUE важно, поскольку без него невозможно установить ограничение внешнего ключа между таблицами GuestbookComments и aspnet_Users.A UNIQUE constraint is important because without it we cannot establish a foreign key constraint between the GuestbookComments and aspnet_Users tables.

После добавления столбца UserId сохраните таблицу, щелкнув значок сохранить на панели инструментов.After adding the UserId column, save the table by clicking on the Save icon in the Toolbar. Присвойте новой таблице имя GuestbookComments.Name the new table GuestbookComments.

У нас есть последняя ошибка для участия в GuestbookComments таблице: необходимо создать ограничение внешнего ключа между столбцом GuestbookComments.UserId и столбцом aspnet_Users.UserId.We have one last issue to attend to with the GuestbookComments table: we need to create a foreign key constraint between the GuestbookComments.UserId column and the aspnet_Users.UserId column. Чтобы добиться этого, щелкните значок связи на панели инструментов, чтобы открыть диалоговое окно связи внешних ключей.To achieve this, click the Relationship icon in the Toolbar to launch the Foreign Key Relationships dialog box. (Также можно запустить это диалоговое окно, перейдя в меню конструктор таблиц и выбрав пункт связи.)(Alternatively, you can launch this dialog box by going to the Table Designer menu and choosing Relationships.)

Нажмите кнопку Добавить в левом нижнем углу диалогового окна связи внешнего ключа.Click the Add button in the lower left corner of the Foreign Key Relationships dialog box. Это приведет к добавлению нового ограничения внешнего ключа, хотя все равно необходимо определить таблицы, участвующие в связи.This will add a new foreign key constraint, although we still need to define the tables that participate in the relationship.

использование диалогового окна связи внешних ключей для управления ограничениями внешнего ключа таблицыUse the Foreign Key Relationships Dialog Box to Manage a Table's Foreign Key Constraints

Рис. 3. диалоговое окно "связи внешнего ключа" используется для управления ограничениями внешнего ключа таблицы (щелкните, чтобы просмотреть изображение с полным размером)Figure 3: Use the Foreign Key Relationships Dialog Box to Manage a Table's Foreign Key Constraints (Click to view full-size image)

Затем щелкните значок с многоточием в строке "спецификации таблиц и столбцов" справа.Next, click the ellipses icon in the "Table and Columns Specifications" row on the right. Откроется диалоговое окно таблицы и столбцы, в котором можно указать таблицу первичного ключа, столбец и внешний ключевой столбец из таблицы GuestbookComments.This will launch the Tables and Columns dialog box, from which we can specify the primary key table and column and the foreign key column from the GuestbookComments table. В частности, выберите aspnet_Users и UserId в качестве таблицы и столбца первичного ключа и UserId из таблицы GuestbookComments в качестве внешнего ключевого столбца (см. рис. 4).In particular, select aspnet_Users and UserId as the primary key table and column, and UserId from the GuestbookComments table as the foreign key column (see Figure 4). Определив первичные и внешние ключи и таблицы и столбцы внешнего ключа, нажмите кнопку ОК, чтобы вернуться в диалоговое окно связи внешних ключей.After defining the primary and foreign key tables and columns, click OK to return to the Foreign Key Relationships dialog box.

установить ограничение внешнего ключа между таблицами aspnet_Users и ГуесбуккомментсEstablish a Foreign Key Constraint Between the aspnet_Users and GuesbookComments Tables

Рис. 4. определение ограничения внешнего ключа между таблицами aspnet_Users и GuesbookComments (щелкните, чтобы просмотреть изображение с полным размером)Figure 4: Establish a Foreign Key Constraint Between the aspnet_Users and GuesbookComments Tables (Click to view full-size image)

На этом этапе было установлено ограничение внешнего ключа.At this point the foreign key constraint has been established. Наличие этого ограничения обеспечивает реляционную целостность двух таблиц, гарантируя тем самым, что никогда не будет являться запись в гостевой книге, ссылающейся на несуществующую учетную запись пользователя.The presence of this constraint ensures relational integrity between the two tables by guaranteeing that there will never be a guestbook entry referring to a non-existent user account. По умолчанию ограничение внешнего ключа запрещает удаление родительской записи при наличии соответствующих дочерних записей.By default, a foreign key constraint will disallow a parent record to be deleted if there are corresponding child records. Это значит, что если пользователь создает одну или несколько комментариев гостевой книги, а затем пытается удалить эту учетную запись пользователя, удаление завершится ошибкой, если сначала не будут удалены комментарии к гостевой книге.That is, if a user makes one or more guestbook comments, and then we attempt to delete that user account, the delete will fail unless his guestbook comments are deleted first.

Ограничения внешнего ключа можно настроить на автоматическое удаление связанных дочерних записей при удалении родительской записи.Foreign key constraints can be configured to automatically delete the associated child records when a parent record is deleted. Иными словами, можно настроить ограничение внешнего ключа таким образом, чтобы записи гостевой книги пользователя автоматически удалялись при удалении учетной записи пользователя.In other words, we can setup this foreign key constraint so that a user's guestbook entries are automatically deleted when her user account is deleted. Для этого разверните раздел "Вставка и обновление спецификации" и задайте для свойства "удалить правило" значение Cascade.To accomplish this, expand the "INSERT And UPDATE Specification" section and set the "Delete Rule" property to Cascade.

настроить ограничение внешнего ключа на каскадное удалениеConfigure the Foreign Key Constraint to Cascade Deletes

Рис. 5. Настройка ограничения внешнего ключа на каскадное удаление (щелкните, чтобы просмотреть изображение с полным размером)Figure 5: Configure the Foreign Key Constraint to Cascade Deletes (Click to view full-size image)

Чтобы сохранить ограничение внешнего ключа, нажмите кнопку "Закрыть", чтобы выйти из связей внешнего ключа.To save the foreign key constraint, click the Close button to exit out of the Foreign Key Relationships. Затем щелкните значок сохранить на панели инструментов, чтобы сохранить таблицу и эту связь.Then click the Save icon in the Toolbar to save the table and the this relationship.

Хранение домашнего города, домашней страницы и подписи пользователяStoring the User's Home Town, Homepage, and Signature

В GuestbookComments таблице показано, как хранить сведения, которые совместно используют связь «один ко многим» с учетными записями пользователей.The GuestbookComments table illustrates how to store information that shares a one-to-many relationship with user accounts. Так как каждая учетная запись пользователя может иметь произвольное количество связанных комментариев, эта связь моделируется путем создания таблицы для хранения набора комментариев, включающих в себя столбец, связывающий каждый комментарий с конкретным пользователем.Since each user account may have an arbitrary number of associated comments, this relationship is modeled by creating a table to hold the set of comments that includes a column that links back each comment to a particular user. При использовании SqlMembershipProviderэту ссылку лучше установить, создав столбец с именем UserId типа uniqueidentifier и ограничение внешнего ключа между этим столбцом и aspnet_Users.UserId.When using the SqlMembershipProvider, this link is best established by creating a column named UserId of type uniqueidentifier and a foreign key constraint between this column and aspnet_Users.UserId.

Теперь нам нужно связать три столбца с каждой учетной записью пользователя для хранения домашнего города пользователя, домашней страницы и подписи, которые будут отображаться в комментариях к гостевой книге.We now need to associate three columns with each user account to store the user's home town, homepage, and signature, which will appear in his guestbook comments. Это можно сделать несколькими способами:There are number of different ways to accomplish this:

  • Добавьте новые столбцы вaspnet_Users или aspnet_Membership таблицы.Add new columns to theaspnet_Usersoraspnet_Membershiptables. Я не рекомендую этот подход, так как он изменяет схему, используемую SqlMembershipProvider.I would not recommend this approach because it modifies the schema used by the SqlMembershipProvider. Это решение может вернуться к хаунт в дороге.This decision may come back to haunt you down the road. Например, если в будущей версии ASP.NET используется другая схема SqlMembershipProvider.For example, what if a future version of ASP.NET uses a different SqlMembershipProvider schema. Корпорация Майкрософт может включить средство для переноса данных ASP.NET 2,0 SqlMembershipProvider в новую схему, но если вы изменили схему ASP.NET 2,0 SqlMembershipProvider, такое преобразование может оказаться невозможным.Microsoft may include a tool to migrate the ASP.NET 2.0 SqlMembershipProvider data to the new schema, but if you have modified the ASP.NET 2.0 SqlMembershipProvider schema, such a conversion may not be possible.

  • Используйте технологию ASP. Инфраструктура профиля NET, определяющая свойство профиля для домашнего города, домашней страницы и подписи.Use ASP.NET's Profile framework, defining a profile property for the home town, homepage, and signature. ASP.NET включает платформу профилей, предназначенную для хранения дополнительных данных, относящихся к пользователю.ASP.NET includes a Profile framework that is designed to store additional user-specific data. Как и в случае с инфраструктурой членства, инфраструктура профилей строится на основе модели поставщика.Like the Membership framework, the Profile framework is built atop the provider model. .NET Framework поставляется с SqlProfileProvider, в котором хранятся данные профиля в SQL Server базе данных.The .NET Framework ships with a SqlProfileProvider that stores profile data in a SQL Server database. На самом деле наша база данных уже содержит таблицу, используемую SqlProfileProvider (aspnet_Profile), так как она была добавлена при добавлении служб приложений обратно в руководство по созданию схемы членства в SQL Server .In fact, our database already has the table used by the SqlProfileProvider (aspnet_Profile), as it was added when we added the application services back in the Creating the Membership Schema in SQL Server tutorial.
    Основным преимуществом платформы Profile Framework является то, что он позволяет разработчикам определять свойства профиля в Web.config — не требуется написание кода для сериализации данных профиля в базовое хранилище данных и из него.The main benefit of the Profile framework is that it allows for developers to define the profile properties in Web.config – no code needs to be written to serialize the profile data to and from the underlying data store. Вкратце, чрезвычайно просто определить набор свойств профиля и работать с ними в коде.In short, it is incredibly easy to define a set of profile properties and to work with them in code. Тем не менее система профиля остается очень необходимой, когда дело доходит до управления версиями, поэтому, если у вас есть приложение, в котором вы предполагаете добавить новые свойства для конкретного пользователя позднее, или удалить или изменить существующие, то платформа профиля может не быть наилучший вариант.However, the Profile system leaves a lot to be desired when it comes to versioning, so if you have an application where you expect new user-specific properties to be added at a later time, or existing ones to be removed or modified, then the Profile framework may not be the best option. Более того, SqlProfileProvider сохраняет свойства профиля в сильно денормализованном виде, делая их более невозможными для выполнения запросов непосредственно по данным профиля (например, количество пользователей в дом Нью-Йорк).Moreover, the SqlProfileProvider stores the profile properties in a highly denormalized fashion, making it next to impossible to run queries directly against the profile data (such as, how many users have a home town of New York).
    Дополнительные сведения о структуре профиля см. в разделе "дополнительные считывания" в конце этого руководства.For more information on the Profile framework, consult the "Further Readings" section at the end of this tutorial.

  • Добавьте эти три столбца в новую таблицу базы данных и установите связь «один к одному» между этой таблицей и aspnet_Users .Add these three columns to a new table in the database and establish a one-to-one relationship between this table andaspnet_Users. Этот подход требует немного больше работы, чем при использовании структуры профиля, но обеспечивает максимальную гибкость в том, как в базе данных моделируются дополнительные свойства пользователя.This approach involves a bit more work than with the Profile framework, but offers maximum flexibility in how the additional user properties are modeled in the database. Это вариант, который мы будем использовать в этом руководстве.This is the option we will use in this tutorial.

Мы создадим новую таблицу с именем UserProfiles, чтобы сохранить домашний город, домашнюю страницу и подпись для каждого пользователя.We will create a new table called UserProfiles to save the home town, homepage, and signature for each user. Щелкните правой кнопкой мыши папку таблицы в окне обозреватель базы данных и выберите создать новую таблицу.Right-click on the Tables folder in the Database Explorer window and choose to create a new table. Присвойте первому столбцу имя UserId и задайте для его типа значение uniqueidentifier.Name the first column UserId and set its type to uniqueidentifier. Запрет NULL значений и Пометка столбца в качестве первичного ключа.Disallow NULL values and mark the column as a primary key. Затем добавьте столбцы с именем: HomeTown типа nvarchar(50); HomepageUrl типа nvarchar(100); и сигнатура типа nvarchar(500).Next, add columns named: HomeTown of type nvarchar(50); HomepageUrl of type nvarchar(100); and Signature of type nvarchar(500). Каждый из этих трех столбцов может принимать значение NULL.Each of these three columns can accept a NULL value.

создания таблицы UserProfilesCreate the UserProfiles Table

Рис. 6. создание таблицы UserProfiles (щелкните, чтобы просмотреть изображение с полным размером)Figure 6: Create the UserProfiles Table (Click to view full-size image)

Сохраните таблицу и назовите ее UserProfiles.Save the table and name it UserProfiles. Наконец, установите ограничение внешнего ключа между UserIdным полем UserProfiles таблицы и полем aspnet_Users.UserId.Lastly, establish a foreign key constraint between the UserProfiles table's UserId field and the aspnet_Users.UserId field. Как и в случае с ограничением внешнего ключа между таблицами GuestbookComments и aspnet_Users, это ограничение каскадным удалением.As we did with the foreign key constraint between the GuestbookComments and aspnet_Users tables, have this constraint cascade deletes. Так как поле UserId в UserProfiles является первичным ключом, это гарантирует, что в таблице UserProfiles для каждой учетной записи пользователя будет не более одной записи.Since the UserId field in UserProfiles is the primary key, this ensures that there will be no more than one record in the UserProfiles table for each user account. Этот тип связи называется "один к одному".This type of relationship is referred to as one-to-one.

Теперь, когда мы создали модель данных, мы готовы к ее использованию.Now that we have the data model created, we are ready to use it. В шагах 2 и 3 мы рассмотрим, как пользователь, выполнивший вход в систему, может просматривать и редактировать домашний город, домашнюю страницу и сведения о подписи.In Steps 2 and 3 we will look at how the currently logged on user can view and edit their home town, homepage, and signature information. На шаге 4 мы создадим интерфейс для пользователей, прошедших проверку подлинности, для отправки новых комментариев в гостевой книге и просмотра существующих.In Step 4 we will create the interface for authenticated users to submit new comments to the guestbook and view the existing ones.

Шаг 2. Отображение домашнего города, домашней страницы и подписи пользователяStep 2: Displaying the User's Home Town, Homepage, and Signature

Существует множество способов разрешить пользователю, вошедшему в систему, просматривать и изменять домашний город, домашнюю страницу и сведения о подписи.There are a variety of ways to allow the currently logged on user to view and edit his home town, homepage, and signature information. Можно вручную создать пользовательский интерфейс с элементами управления TextBox и Label или использовать один из веб-элементов управления данными, например элемент управления DetailsView.We could manually create the user interface with TextBox and Label controls or we could use one of the data Web controls, such as the DetailsView control. Для выполнения SELECT базы данных и UPDATE инструкций можно написать код ADO.NET в классе кода программной части страницы или же использовать декларативный подход с SqlDataSource.To perform the database SELECT and UPDATE statements we could write ADO.NET code in our page's code-behind class or, alternatively, employ a declarative approach with the SqlDataSource. В идеале наше приложение будет содержать многоуровневую архитектуру, которую можно либо вызывать программно из класса кода программной части страницы, либо декларативно с помощью элемента управления ObjectDataSource.Ideally our application would contain a tiered architecture, which we could either invoke programmatically from the page's code-behind class or declaratively via the ObjectDataSource control.

Поскольку эта серия руководств посвящена проверке подлинности на основе форм, авторизации, учетных записей пользователей и ролей, не будет подробно обсуждать эти различные варианты доступа к данным или почему многоуровневая архитектура предпочтительнее непосредственного выполнения инструкций SQL. на странице ASP.NET.Since this tutorial series focuses on forms authentication, authorization, user accounts, and roles, there will not be a thorough discussion of these different data access options or why a tiered architecture is preferred over executing SQL statements directly from the ASP.NET page. Я покажу, как использовать DetailsView и SqlDataSource — самый быстрый и простой способ — но описанные концепции можно применять к альтернативным веб-элементам управления и логике доступа к данным.I am going to walk through using a DetailsView and SqlDataSource – the quickest and easiest option – but the concepts discussed can certainly be applied to alternative Web controls and data access logic. Дополнительные сведения о работе с данными в ASP.NET см. в статье Руководство по работе с данными в ASP.NET 2,0 .For more information on working with data in ASP.NET, refer to my Working with Data in ASP.NET 2.0 tutorial series.

Откройте страницу AdditionalUserInfo.aspx в папке Membership и добавьте на страницу элемент управления DetailsView, присвоив свойству ID значение UserProfile и удалив его свойства Width и Height.Open the AdditionalUserInfo.aspx page in the Membership folder and add a DetailsView control to the page, setting its ID property to UserProfile and clearing out its Width and Height properties. Разверните смарт-тег DetailsView и выберите его привязку к новому элементу управления источниками данных.Expand the DetailsView's Smart Tag and choose to bind it to a new data source control. Запустится мастер настройки источника данных (см. рис. 7).This will launch the DataSource Configuration Wizard (see Figure 7). На первом шаге будет предложено указать тип источника данных.The first step asks you to specify the data source type. Так как мы будем подключаться непосредственно к базе данных SecurityTutorials, щелкните значок базы данных, указав ID как UserProfileDataSource.Since we are going to connect directly to the SecurityTutorials database, choose the Database icon, specifying the ID as UserProfileDataSource.

добавить новый элемент управления SqlDataSource с именем УсерпрофиледатасаурцеAdd a New SqlDataSource Control Named UserProfileDataSource

Рис. 7. Добавление нового элемента управления SqlDataSource с именем UserProfileDataSource (щелкните, чтобы просмотреть изображение с полным размером)Figure 7: Add a New SqlDataSource Control Named UserProfileDataSource (Click to view full-size image)

На следующем экране запрашивается использование базы данных.The next screen prompts for the database to use. Мы уже определили строку подключения в Web.config для базы данных SecurityTutorials.We have already defined a connection string in Web.config for the SecurityTutorials database. Это имя строки подключения — SecurityTutorialsConnectionString — должно быть в раскрывающемся списке.This connection string name – SecurityTutorialsConnectionString – should be in the drop-down list. Выберите этот параметр и нажмите кнопку Далее.Select this option and click Next.

выберите Секурититуториалсконнектионстринг из раскрывающегося списка.Choose SecurityTutorialsConnectionString from the Drop-Down List

Рис. 8. Выбор SecurityTutorialsConnectionString из раскрывающегося списка (щелкните, чтобы просмотреть изображение с полным размером)Figure 8: Choose SecurityTutorialsConnectionString from the Drop-Down List (Click to view full-size image)

На следующем экране будет предложено указать таблицу и столбцы для запроса.The subsequent screen asks us to specify the table and columns to query. Выберите таблицу UserProfiles из раскрывающегося списка и проверьте все столбцы.Choose the UserProfiles table from the drop-down list and check all of the columns.

вернуть все столбцы из таблицы UserProfilesBring Back All of the Columns from the UserProfiles Table

Рис. 9. возврат всех столбцов из таблицы UserProfiles (щелкните, чтобы просмотреть изображение с полным размером)Figure 9: Bring Back All of the Columns from the UserProfiles Table (Click to view full-size image)

Текущий запрос на рис. 9 возвращает все записи в UserProfiles, но мы заинтересованы только в записи текущего пользователя, вошедшего в систему.The current query in Figure 9 returns all of the records in UserProfiles, but we are only interested in the currently logged on user's record. Чтобы добавить предложение WHERE, нажмите кнопку WHERE, чтобы открыть диалоговое окно Добавление предложения WHERE (см. рис. 10).To add a WHERE clause, click the WHERE button to bring up the Add WHERE Clause dialog box (see Figure 10). Здесь можно выбрать столбец для фильтрации, оператор и источник параметра фильтра.Here you can select the column to filter on, the operator, and the source of the filter parameter. В качестве оператора выберите UserId в качестве столбца и "=".Select UserId as the column and "=" as the Operator.

К сожалению, нет встроенного источника параметров для возврата значения UserId текущего пользователя, вошедшего в систему.Unfortunately there is no built-in parameter source to return the currently logged on user's UserId value. Это значение необходимо извлечь программно.We will need to grab this value programmatically. Поэтому в раскрывающемся списке Источник выберите значение нет, нажмите кнопку Добавить, чтобы добавить параметр, а затем нажмите кнопку ОК.Therefore, set the Source drop-down list to "None," click the Add button to add the parameter, and then click OK.

добавить параметр фильтра в столбец UserIdAdd a Filter Parameter on the UserId Column

Рис. 10. Добавление параметра фильтра в столбец UserId (щелкните, чтобы просмотреть изображение с полным размером)Figure 10: Add a Filter Parameter on the UserId Column (Click to view full-size image)

После нажатия кнопки ОК вы вернетесь на экран, показанный на рис. 9.After clicking OK you will be returned to the screen shown in Figure 9. Однако на этот раз SQL-запрос в нижней части экрана должен содержать предложение WHERE.This time, however, the SQL query at the bottom of the screen should include a WHERE clause. Нажмите кнопку Далее, чтобы перейти на экран тестовый запрос.Click Next to move on to the "Test Query" screen. Здесь можно выполнить запрос и просмотреть результаты.Here you can run the query and see the results. Нажмите кнопку Готово, чтобы завершить работу с мастером.Click Finish to complete the wizard.

После завершения работы мастера настройки источника данных Visual Studio создает элемент управления SqlDataSource на основе параметров, заданных в мастере.Upon completing the DataSource Configuration Wizard, Visual Studio creates the SqlDataSource control based on the settings specified in the wizard. Более того, он вручную добавляет BoundFields к элементу DetailsView для каждого столбца, возвращаемого SelectCommandом SqlDataSource.Moreover, it manually adds BoundFields to the DetailsView for each column returned by the SqlDataSource's SelectCommand. Нет необходимости показывать поле UserId в DetailsView, так как пользователю не нужно знать это значение.There's no need to show the UserId field in the DetailsView, since the user does not need to know this value. Это поле можно удалить непосредственно из декларативной разметки элемента управления DetailsView или щелкнув ссылку "изменить поля" из своего смарт-тега.You can remove this field directly from the DetailsView control's declarative markup or by clicking the "Edit Fields" link from its Smart Tag.

На этом этапе декларативная разметка страницы должна выглядеть следующим образом:At this point your page's declarative markup should look similar to the following:

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

Прежде чем выбирать данные, необходимо программно задать параметр UserId элемента управления SqlDataSource до UserId текущего пользователя.We need to programmatically set the SqlDataSource control's UserId parameter to the currently logged in user's UserId before the data is selected. Это можно сделать, создав обработчик событий для события Selecting SqlDataSource и добавив следующий код:This can be accomplished by creating an event handler for the SqlDataSource's Selecting event and adding the following code there:

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.The above code starts by obtaining a reference to the currently logged on user by calling the Membership class's GetUser method. Он возвращает объект MembershipUser, свойство ProviderUserKey которого содержит UserId.This returns a MembershipUser object, whose ProviderUserKey property contains the UserId. Затем значение UserId присваивается параметру @UserId SqlDataSource.The UserId value is then assigned to the SqlDataSource's @UserId parameter.

Note

Метод Membership.GetUser() возвращает сведения о вошедшем в систему пользователе.The Membership.GetUser() method returns information about the currently logged on user. Если анонимный пользователь посещает страницу, он возвратит значение Nothing.If an anonymous user is visiting the page, it will return a value of Nothing. В этом случае это приводит к NullReferenceExceptionу в следующей строке кода при попытке чтения свойства ProviderUserKey.In such a case, this will lead to a NullReferenceException on the following line of code when attempting to read the ProviderUserKey property. Конечно, нам не нужно беспокоиться о том, Membership.GetUser() ничего не возвращает на страницу AdditionalUserInfo.aspx, так как мы настроили авторизацию URL-адресов в предыдущем учебнике, чтобы только пользователи, прошедшие проверку подлинности, могли получить доступ к ресурсам ASP.NET в этой папке.Of course, we don't have to worry about Membership.GetUser() returning Nothing in the AdditionalUserInfo.aspx page because we configured URL authorization in a previous tutorial so that only authenticated users could access the ASP.NET resources in this folder. Если необходимо получить доступ к сведениям о вошедшем в систему пользователе на странице, где разрешен анонимный доступ, убедитесь, что объект MembershipUser, возвращенный методом GetUser(), не является Nothing, прежде чем ссылаться на его свойства.If you need to access information about the currently logged on user in a page where anonymous access is permitted, make sure to check that the MembershipUser object returned from the GetUser() method is not Nothing before referencing its properties.

Если вы посещаете страницу AdditionalUserInfo.aspx в браузере, вы увидите пустую страницу, так как нам еще не нужно добавлять какие-либо строки в таблицу UserProfiles.If you visit the AdditionalUserInfo.aspx page through a browser you will see a blank page because we have yet to add any rows to the UserProfiles table. На шаге 6 мы рассмотрим, как настроить элемент управления CreateUserWizard для автоматического добавления новой строки в таблицу UserProfiles при создании новой учетной записи пользователя.In Step 6 we will look at how to customize the CreateUserWizard control to automatically add a new row to the UserProfiles table when a new user account is created. Однако теперь необходимо вручную создать запись в таблице.For now, however, we will need to manually create a record in the table.

Перейдите к обозреватель базы данных в Visual Studio и разверните папку таблицы.Navigate to the Database Explorer in Visual Studio and expand the Tables folder. Щелкните правой кнопкой мыши таблицу aspnet_Users и выберите команду "Показать данные таблицы", чтобы просмотреть записи в таблице. Сделайте то же самое для таблицы UserProfiles.Right-click on the aspnet_Users table and choose "Show Table Data" to see the records in the table; do the same thing for the UserProfiles table. На рис. 11 показаны эти результаты при вертикальном мозаичном заполнении.Figure 11 shows these results when tiled vertically. В базе данных в настоящее время aspnet_Users записи для Брюс, Fred и Тито, но нет записей в таблице UserProfiles.In my database there are currently aspnet_Users records for Bruce, Fred, and Tito, but no records in the UserProfiles table.

отображается содержимое таблиц aspnet_Users и UserProfileThe Contents of the aspnet_Users and UserProfiles Tables are Displayed

Рис. 11. Отображение содержимого таблиц aspnet_Users и UserProfiles (щелкните, чтобы просмотреть изображение с полным размером)Figure 11: The Contents of the aspnet_Users and UserProfiles Tables are Displayed (Click to view full-size image)

Добавьте новую запись в UserProfiles таблицу, введя значения полей HomeTown, HomepageUrlи Signature вручную.Add a new record to the UserProfiles table by manually typing in values for the HomeTown, HomepageUrl, and Signature fields. Самый простой способ получить допустимое значение UserId в новой записи UserProfiles — выбрать поле UserId из определенной учетной записи пользователя в таблице aspnet_Users, а затем скопировать и вставить его в поле UserId в UserProfiles.The easiest way to get a valid UserId value in the new UserProfiles record is to select the UserId field from a particular user account in the aspnet_Users table and copy and paste it into the UserId field in UserProfiles. На рис. 12 показана UserProfilesная таблица после добавления новой записи для Брюс.Figure 12 shows the UserProfiles table after a new record has been added for Bruce.

запись была добавлена к профилям пользователя для БрюсA Record was Added to UserProfiles for Bruce

Рис. 12. запись добавлена в UserProfiles для Брюс (щелкните, чтобы просмотреть изображение с полным размером)Figure 12: A Record was Added to UserProfiles for Bruce (Click to view full-size image)

Вернитесь к AdditionalUserInfo.aspx page, войдя в систему как Брюс.Return to the AdditionalUserInfo.aspx page, logged in as Bruce. Как показано на рис. 13, отображаются параметры Брюс.As Figure 13 shows, Bruce's settings are displayed.

отображаются параметры текущего пользователя.The Currently Visiting User is Shown His Settings

Рис. 13. сведения о текущем посещенном пользователе отображаются в его настройках (щелкните, чтобы просмотреть изображение с полным размером)Figure 13: The Currently Visiting User is Shown His Settings (Click to view full-size image)

Note

Вручную добавьте записи в таблицу UserProfiles для каждого пользователя членства.Go ahead and manually add records in the UserProfiles table for each Membership user. На шаге 6 мы рассмотрим, как настроить элемент управления CreateUserWizard для автоматического добавления новой строки в таблицу UserProfiles при создании новой учетной записи пользователя.In Step 6 we will look at how to customize the CreateUserWizard control to automatically add a new row to the UserProfiles table when a new user account is created.

Шаг 3. Разрешение пользователю на изменение домашнего города, домашней страницы и подписиStep 3: Allowing the User to Edit His Home Town, Homepage, and Signature

На этом этапе текущий пользователь, выполнивший вход в систему, может просматривать свои домашние город, домашнюю страницу и параметры подписи, но они пока не могут изменить их.At this point the currently logged in user can view their home town, homepage, and signature setting, but they cannot yet modify them. Давайте изменим элемент управления DetailsView, чтобы можно было изменять данные.Let's update the DetailsView control so that the data can be edited.

Первое, что нам нужно сделать, — это добавить UpdateCommand для SqlDataSource, указав инструкцию UPDATE для выполнения и соответствующие параметры.The first thing we need to do is add an UpdateCommand for the SqlDataSource, specifying the UPDATE statement to execute and its corresponding parameters. Выберите элемент SqlDataSource и в окно свойств щелкните многоточие рядом со свойством Упдатекуери, чтобы открыть диалоговое окно Редактор параметров и команд.Select the SqlDataSource and, from the Properties window, click on the ellipses next to the UpdateQuery property to bring up the Command and Parameter Editor dialog box. Введите следующую инструкцию UPDATE в текстовое поле:Enter the following UPDATE statement into the textbox:

UPDATE UserProfiles SET
     HomeTown = @HomeTown,
     HomepageUrl = @HomepageUrl,
     Signature = @Signature
WHERE UserId = @UserId

Затем нажмите кнопку "обновить параметры", которая создаст параметр в коллекции UpdateParameters элемента управления SqlDataSource для каждого из параметров в инструкции UPDATE.Next, click the "Refresh Parameters" button, which will create a parameter in the SqlDataSource control's UpdateParameters collection for each of the parameters in the UPDATE statement. Оставьте в поле источник все параметры, для которых установлено значение нет, и нажмите кнопку ОК, чтобы закрыть диалоговое окно.Leave the source for all of the parameters set to None and click the OK button to complete the dialog box.

указать UpdateCommand и UpdateParameters для SqlDataSourceSpecify the SqlDataSource's UpdateCommand and UpdateParameters

Рис. 14. Указание UpdateCommand и UpdateParameters SqlDataSource (щелкните, чтобы просмотреть изображение с полным размером)Figure 14: Specify the SqlDataSource's UpdateCommand and UpdateParameters (Click to view full-size image)

Из-за дополнений к элементу управления SqlDataSource элемент управления DetailsView теперь может поддерживать редактирование.Due to the additions we made to the SqlDataSource control, the DetailsView control can now support editing. В смарт-теге DetailsView установите флажок "Разрешить изменение".From the DetailsView's Smart Tag, check the "Enable Editing" checkbox. При этом в коллекцию Fields элемента управления добавляется CommandField со свойством ShowEditButton, установленным в значение true.This adds a CommandField to the control's Fields collection with its ShowEditButton property set to True. При отображении элемента DetailsView в режиме только для чтения и кнопках обновить и Отмена в режиме редактирования отображается кнопка Изменить.This renders an Edit button when the DetailsView is displayed in read-only mode and Update and Cancel buttons when displayed in edit mode. Однако, вместо того чтобы требовать от пользователя нажатия кнопки изменить, можно отобразить элемент DetailsView в состоянии "всегда изменять", установив для свойстваDefaultMode элемента управления detailsview значение Edit.Rather than requiring the user to click Edit, though, we can have the DetailsView render in an "always editable" state by setting the DetailsView control's DefaultMode property to Edit.

После внесения этих изменений декларативная разметка элемента управления DetailsView должна выглядеть следующим образом:With these changes, your DetailsView control's declarative markup should look similar to the following:

<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.Note the addition of the CommandField and the DefaultMode property.

Протестируйте эту страницу в браузере.Go ahead and test this page through a browser. При посещении с пользователем, имеющим соответствующую запись в UserProfiles, параметры пользователя отображаются в изменяемом интерфейсе.When visiting with a user that has a corresponding record in UserProfiles, the user's settings are displayed in an editable interface.

элемент DetailsView визуализирует редактируемый интерфейсThe DetailsView Renders an Editable Interface

Рис. 15. элемент DetailsView визуализирует редактируемый интерфейс (щелкните, чтобы просмотреть изображение с полным размером)Figure 15: The DetailsView Renders an Editable Interface (Click to view full-size image)

Попробуйте изменить значения и нажмите кнопку Обновить.Try changing the values and clicking the Update button. Оно кажется, если ничего не происходит.It appears as if nothing happens. Обратная передача и значения сохраняются в базе данных, но визуальная обратная связь, возникшая при сохранении, отсутствует.There is a postback and the values are saved to the database, but there's no visual feedback that the save occurred.

Чтобы устранить эту проблему, вернитесь в Visual Studio и добавьте элемент управления Label над элементом DetailsView.To remedy this, return to Visual Studio and add a Label control above the DetailsView. Задайте для его ID значение SettingsUpdatedMessage, его свойству Text значение "ваши параметры обновлены", а для свойств Visible и EnableViewStateFalse.Set its ID to SettingsUpdatedMessage, its Text property to "Your settings have been updated," and its Visible and EnableViewState properties to False.

<asp:Label ID="SettingsUpdatedMessage" runat="server"
     Text="Your settings have been updated."
     EnableViewState="false"
     Visible="false">
</asp:Label>

При каждом обновлении элемента DetailsView необходимо отображать метку SettingsUpdatedMessage.We need to display the SettingsUpdatedMessage Label whenever the DetailsView is updated. Для этого создайте обработчик событий для события ItemUpdated DetailsView и добавьте следующий код:To accomplish this, create an event handler for the DetailsView's ItemUpdated event and add the following code:

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 страницу в браузере и обновите данные.Return to the AdditionalUserInfo.aspx page through a browser and update the data. На этот раз отображается полезное сообщение о состоянии.This time, a helpful status message is displayed.

при обновлении параметров отображается короткое сообщениеA Short Message is Displayed When the Settings are Updated

Рис. 16. при обновлении параметров отображается короткое сообщение (щелкните, чтобы просмотреть изображение с полным размером)Figure 16: A Short Message is Displayed When the Settings are Updated (Click to view full-size image)

Note

Интерфейс правки элемента управления DetailsView оставляет много необходимости.The DetailsView control's editing interface leaves a lot to be desired. В ней используются текстовые поля стандартного размера, но поле подписи, возможно, является многострочным текстовым полем.It uses standard-sized textboxes, but the Signature field should probably be a multi-line textbox. Регуларекспрессионвалидатор должен использоваться, чтобы гарантировать, что URL-адрес домашней страницы, если он указан, начинается с "http://" или "https://".A RegularExpressionValidator should be used to ensure that the homepage URL, if entered, starts with "http://" or "https://". Более того, поскольку для элемента управления DetailsView свойство DefaultMode имеет значение Edit, кнопка Отмена не выполняет никаких действий.Moreover, since the DetailsView control has its DefaultMode property set to Edit, the Cancel button does not do anything. Он должен быть либо удален, либо, при щелчке, перенаправлять пользователя на другую страницу (например, ~/Default.aspx).It should either be removed or, when clicked, redirect the user to some other page (such as ~/Default.aspx). Я оставлю эти улучшения в качестве упражнения для читателя.I leave these enhancements as an exercise for the reader.

В настоящее время веб-сайт не предоставляет ссылки на страницу AdditionalUserInfo.aspx.Currently, the website does not provide any links to the AdditionalUserInfo.aspx page. Единственный способ достичь этого — ввести URL-адрес страницы непосредственно в адресную строку браузера.The only way to reach it is to enter the page's URL directly into the browser's Address bar. Давайте добавим ссылку на эту страницу на главной странице Site.master.Let's add a link to this page in the Site.master master page.

Вспомним, что Главная страница содержит веб-элемент управления LoginView в его LoginContent ContentPlaceHolder, который отображает различную разметку для прошедших проверку подлинности и анонимных посетителей.Recall that the master page contains a LoginView Web control in its LoginContent ContentPlaceHolder that displays different markup for authenticated and anonymous visitors. Обновите LoggedInTemplate элемента управления LoginView, чтобы включить ссылку на страницу AdditionalUserInfo.aspx.Update the LoginView control's LoggedInTemplate to include a link to the AdditionalUserInfo.aspx page. После внесения этих изменений декларативная разметка элемента управления LoginView должна выглядеть следующим образом:After making these changes the LoginView control's declarative markup should look similar to the following:

<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.Note the addition of the lnkUpdateSettings HyperLink control to the LoggedInTemplate. С помощью этой ссылки пользователи, прошедшие проверку подлинности, могут быстро перейти на страницу, чтобы просмотреть и изменить параметры домашнего города, домашней страницы и подписи.With this link in place, authenticated users can quickly jump to the page to view and modify their home town, homepage, and signature settings.

Шаг 4. Добавление новых комментариев к гостевой книгеStep 4: Adding New Guestbook Comments

Страница Guestbook.aspx, где пользователи с проверкой подлинности могут просматривать гостевую книгу и оставлять комментарий.The Guestbook.aspx page is where authenticated users can view the guestbook and leave a comment. Начнем с создания интерфейса для добавления новых комментариев гостевой книги.Let's start with creating the interface to add new guestbook comments.

Откройте страницу Guestbook.aspx в Visual Studio и создайте пользовательский интерфейс, состоящий из двух элементов управления TextBox: один для темы нового комментария и один для его тела.Open the Guestbook.aspx page in Visual Studio and construct a user interface consisting of two TextBox controls, one for the new comment's subject and one for its body. Присвойте свойству ID первого текстового элемента управления значение Subject, а свойству Columns — значение 40; Задайте для второго ID значение Body, его TextMode MultiLine, а также Width и Rows свойства в значение "95%" и 8 соответственно.Set the first TextBox control's ID property to Subject and its Columns property to 40; set second's ID to Body, its TextMode to MultiLine, and its Width and Rows properties to "95%" and 8, respectively. Чтобы завершить пользовательский интерфейс, добавьте веб-элемент управления Button с именем PostCommentButton и задайте для его свойства Text значение "опубликовать комментарий".To complete the user interface, add a Button Web control named PostCommentButton and set its Text property to "Post Your Comment".

Поскольку каждому комментарию гостевой книги требуется тема и текст, добавьте RequiredFieldValidator для каждого из текстовых полей.Since each guestbook comment requires a subject and body, add a RequiredFieldValidator for each of the TextBoxes. Задайте для свойства ValidationGroup этих элементов управления значение "Ентеркоммент". Аналогичным образом задайте для свойства ValidationGroup элемента управления PostCommentButton значение "Ентеркоммент".Set the ValidationGroup property of these controls to "EnterComment"; likewise, set the PostCommentButton control's ValidationGroup property to "EnterComment". Дополнительные сведения о ASP. Элементы управления проверки в сети, изучите проверку формы в ASP.NET, которая разбила элементы управления проверки в ASP.NET 2,0, а также учебник по элементам управления сервера проверки в W3Schools.For more information on ASP.NET's validation controls, check out Form Validation in ASP.NET, Dissecting the Validation Controls in ASP.NET 2.0, and the Validation Server Controls Tutorial on W3Schools.

После создания пользовательского интерфейса декларативная разметка страницы должна выглядеть примерно следующим образом:After crafting the user interface your page's declarative markup should look something like the following:

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

После завершения работы с пользовательским интерфейсом нашей следующей задачей является вставка новой записи в таблицу GuestbookComments при нажатии на PostCommentButton.With the user interface complete, our next task is to insert a new record into the GuestbookComments table when the PostCommentButton is clicked. Это можно сделать несколькими способами: можно написать код ADO.NET в обработчике событий Click кнопки. на страницу можно добавить элемент управления SqlDataSource, настроить его InsertCommand, а затем вызвать его метод Insert из обработчика событий Click. или можно создать средний уровень, отвечающий за вставку новых комментариев гостевой книги, и вызвать эту функцию из обработчика Click событий.This can be accomplished in a number of ways: we can write ADO.NET code in the Button's Click event handler; we can add a SqlDataSource control to the page, configure its InsertCommand, and then call its Insert method from the Click event handler; or we could build a middle tier that was responsible for inserting new guestbook comments, and invoke this functionality from the Click event handler. Так как мы рассматривали использование SqlDataSource на шаге 3, давайте используем здесь код ADO.NET.Since we looked at using a SqlDataSource in Step 3, let's use ADO.NET code here.

Note

Классы ADO.NET, используемые для программного доступа к данным из базы данных Microsoft SQL Server, находятся в пространстве имен System.Data.SqlClient.The ADO.NET classes used to programmatically access data from a Microsoft SQL Server database are located in the System.Data.SqlClient namespace. Может потребоваться импортировать это пространство имен в класс кода программной части страницы (т. е. Imports System.Data.SqlClient).You may need to import this namespace into your page's code-behind class (i.e., Imports System.Data.SqlClient).

Создайте обработчик событий для Click события PostCommentButtonи добавьте следующий код:Create an event handler for the PostCommentButton's Click event and add the following code:

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 начинает с проверки допустимости предоставленных пользователем данных.The Click event handler starts by checking that the user-supplied data is valid. Если это не так, обработчик событий завершает работу перед вставкой записи.If it is not, the event handler exits before inserting a record. Предполагая, что предоставленные данные допустимы, UserId значение текущего пользователя, вошедшего в систему, извлекается и сохраняется в currentUserId локальной переменной.Assuming the supplied data is valid, the currently logged on user's UserId value is retrieved and stored in the currentUserId local variable. Это значение требуется, поскольку при вставке записи в GuestbookCommentsнеобходимо указать значение UserId.This value is needed because we must supply a UserId value when inserting a record into GuestbookComments.

После этого строка подключения для базы данных SecurityTutorials извлекается из Web.config и указывается инструкция SQL INSERT.Following that, the connection string for the SecurityTutorials database is retrieved from Web.config and the INSERT SQL statement is specified. Затем создается и открывается объект SqlConnection.A SqlConnection object is then created and opened. Затем создается объект SqlCommand и приводятся значения параметров, используемых в запросе INSERT.Next, a SqlCommand object is constructed and the values for the parameters used in the INSERT query are assigned. Затем выполняется инструкция INSERT и соединение закрывается.The INSERT statement is then executed and the connection closed. В конце обработчика событий Text свойства Subject и Body текстовые поля удаляются, чтобы значения пользователя не сохранялись во время обратной передачи.At the end of the event handler, the Subject and Body TextBoxes' Text properties are cleared out so that the user's values are not persisted across the postback.

Протестируйте эту страницу в браузере.Go ahead and test out this page in a browser. Так как эта страница находится в папке Membership, она недоступна для анонимных посетителей.Since this page is in the Membership folder it is not accessible to anonymous visitors. Поэтому сначала необходимо войти в систему (если вы еще не сделали этого).Therefore, you will need to first log on (if you have not already). Введите значение в поля Subject и Body и нажмите кнопку PostCommentButton.Enter a value into the Subject and Body TextBoxes and click the PostCommentButton button. Это приведет к добавлению новой записи в GuestbookComments.This will cause a new record to be added to GuestbookComments. При обратной передаче указанная тема и текст очищаются из текстовых полей.On postback, the subject and body you provided are wiped from the TextBoxes.

После нажатия кнопки PostCommentButton нет визуального отзыва о том, что комментарий добавлен в гостевую книгу.After clicking the PostCommentButton button there is no visual feedback that the comment was added to the guestbook. Нам по-прежнему нужно обновить эту страницу, чтобы отобразить комментарии к существующей гостевой книге, которые мы будем делать на шаге 5.We still need to update this page to display the existing guestbook comments, which we will do in Step 5. После этого только что добавленный комментарий появится в списке комментариев, предоставляя достаточный визуальный отзыв.Once we accomplish that, the just-added comment will appear in the list of comments, providing adequate visual feedback. Пока убедитесь, что комментарий к гостевой книге сохранен, проверив содержимое таблицы GuestbookComments.For now, confirm that your guestbook comment was saved by examining the contents of the GuestbookComments table.

На рис. 17 показано содержимое таблицы GuestbookComments после того, как были оставлены два комментария.Figure 17 shows the contents of the GuestbookComments table after two comments have been left.

вы видите комментарии к гостевой книге в таблице ГуестбуккомментсYou Can See the Guestbook Comments in the GuestbookComments Table

Рис. 17. комментарии к гостевой книге можно просмотреть в таблице GuestbookComments (щелкните, чтобы просмотреть изображение с полным размером).Figure 17: You Can See the Guestbook Comments in the GuestbookComments Table (Click to view full-size image)

Note

Если пользователь пытается вставить комментарий гостевой книги, содержащий потенциально опасную разметку, например HTML – ASP.NET, выдается исключение HttpRequestValidationException.If a user attempts to insert a guestbook comment that contains potentially dangerous markup – such as HTML – ASP.NET will throw an HttpRequestValidationException. Чтобы узнать больше об этом исключении, о том, почему оно выдается и как позволить пользователям отправлять потенциально опасные значения, ознакомьтесь с документом о проверке запросов.To learn more about this exception, why it's thrown, and how to permit users to submit potentially dangerous values, consult the Request Validation Whitepaper.

Шаг 5. Перечисление существующих комментариев гостевой книгиStep 5: Listing the Existing Guestbook Comments

Кроме комментариев, пользователь, посещаемый на странице Guestbook.aspx, также должен иметь возможность просматривать существующие комментарии в гостевой книге.In addition to leaving comments, a user visiting the Guestbook.aspx page should also be able to view the guestbook's existing comments. Для этого добавьте элемент управления ListView с именем CommentList в нижнюю часть страницы.To accomplish this, add a ListView control named CommentList to the bottom of the page.

Note

Элемент управления ListView является новым для ASP.NET версии 3,5.The ListView control is new to ASP.NET version 3.5. Он предназначен для вывода списка элементов в очень настраиваемом и гибком макете, но по-прежнему предлагает встроенные функции редактирования, вставки, удаления, разбиения на страницы и сортировки, например GridView.It is designed to display a list of items in a very customizable and flexible layout, yet still offer built-in editing, inserting, deleting, paging, and sorting functionality like the GridView. При использовании ASP.NET 2,0 необходимо использовать элемент управления DataList или Repeater.If you are using ASP.NET 2.0, you will need to use the DataList or Repeater control instead. Дополнительные сведения об использовании ListView см. в записях блога Скотта Гатри (, элементе управления ASP: ListViewи моей статье Отображение данных с помощью элемента управления ListView.For more information on using the ListView, see Scott Guthrie's blog entry, The asp:ListView Control, and my article, Displaying Data with the ListView Control.

Откройте смарт-тег ListView и в раскрывающемся списке Выбор источника данных привяжите элемент управления к новому источнику данных.Open the ListView's Smart Tag and, from the Choose Data Source drop-down list, bind the control to a new data source. Как было показано на шаге 2, это приведет к запуску мастера настройки источника данных.As we saw in Step 2, this will launch the Data Source Configuration Wizard. Щелкните значок базы данных, присвойте результирующему CommentsDataSourceу SqlDataSource имя и нажмите кнопку ОК.Select the Database icon, name the resulting SqlDataSource CommentsDataSource, and click OK. Затем выберите строку подключения SecurityTutorialsConnectionString из раскрывающегося списка и нажмите кнопку Далее.Next, select the SecurityTutorialsConnectionString connection string from the drop-down list and click Next.

На этом этапе в шаге 2 мы указали данные для запроса, выбирая UserProfiles таблицу из раскрывающегося списка и выбрав возвращаемые столбцы (см. рис. 9).At this point in Step 2 we specified the data to query by picking the UserProfiles table from the drop-down list and selecting the columns to return (refer back to Figure 9). Но на этот раз мы хотим создать инструкцию SQL, которая извлекает не только записи из GuestbookComments, но и домашний город, Домашняя страница, подпись и имя пользователя.This time, however, we want to craft a SQL statement that pulls back not only the records from GuestbookComments, but also the commenter's home town, homepage, signature, and username. Поэтому выберите переключатель "указать пользовательскую инструкцию SQL или хранимую процедуру" и нажмите кнопку "Далее".Therefore, select the "Specify a custom SQL statement or stored procedure" radio button and click Next.

Откроется экран "Определение пользовательских инструкций или хранимых процедур".This will bring up the "Define Custom Statements or Stored Procedures" screen. Нажмите кнопку конструктор запросов, чтобы построить графический запрос.Click the Query Builder button to graphically build the query. Конструктор запросов начинается с запроса на указание таблиц, из которых нужно выполнить запрос.The Query Builder starts by prompting us to specify the tables we want to query from. Выберите таблицы GuestbookComments, UserProfilesи aspnet_Users и нажмите кнопку ОК.Select the GuestbookComments, UserProfiles, and aspnet_Users tables and click OK. Это приведет к добавлению всех трех таблиц в область конструктора.This will add all three tables to the design surface. Поскольку существуют ограничения внешнего ключа для таблиц GuestbookComments, UserProfilesи aspnet_Users, конструктор запросов автоматически JOIN эти таблицы.Since there are foreign key constraints amongst the GuestbookComments, UserProfiles, and aspnet_Users tables, the Query Builder automatically JOIN s these tables.

Остается только указать возвращаемые столбцы.All that remains is to specify the columns to return. В таблице GuestbookComments выберите столбцы Subject, Bodyи CommentDate. возвращают столбцы HomeTown, HomepageUrlи Signature из таблицы UserProfiles. и возвращают UserName из aspnet_Users.From the GuestbookComments table select the Subject, Body, and CommentDate columns; return the HomeTown, HomepageUrl, and Signature columns from the UserProfiles table; and return UserName from aspnet_Users. Кроме того, добавьте "ORDER BY CommentDate DESC" в конец запроса SELECT, чтобы последние записи возвращались первыми.Also, add "ORDER BY CommentDate DESC" to the end of the SELECT query so that the most recent posts are returned first. После выбора этих параметров интерфейс конструктор запросов должен выглядеть примерно так, как на снимке экрана на рис. 18.After making these selections, your Query Builder interface should look similar to the screen shot in Figure 18.

построенный запрос объединяет таблицы Гуестбуккомментс, UserProfile и aspnet_UsersThe Constructed Query JOINs the GuestbookComments, UserProfiles, and aspnet_Users Tables

Рис. 18. сконструированный запрос JOIN таблицы GuestbookComments, UserProfilesи aspnet_Users (щелкните,чтобы просмотреть изображение с полным размером)Figure 18: The Constructed Query JOIN s the GuestbookComments, UserProfiles, and aspnet_Users Tables (Click to view full-size image)

Нажмите кнопку ОК, чтобы закрыть окно конструктор запросов и вернуться к экрану "Определение пользовательских инструкций или хранимых процедур".Click OK to close the Query Builder window and return to the "Define Custom Statements or Stored Procedures" screen. Нажмите кнопку Далее, чтобы перейти на экран тестовый запрос, где можно просмотреть результаты запроса, нажав кнопку проверить запрос.Click Next to advance to the "Test Query" screen, where you may view the query results by clicking the Test Query button. Когда будете готовы, нажмите кнопку Готово, чтобы завершить работу мастера настройки источника данных.When you're ready, click Finish to complete the Configure Data Source wizard.

После завершения работы мастера настройки источника данных на шаге 2 связанная коллекция Fields элемента управления DetailsView была обновлена для включения BoundField для каждого столбца, возвращаемого SelectCommand.When we completed the Configure Data Source wizard in Step 2, the associated DetailsView control's Fields collection was updated to include a BoundField for each column returned by the SelectCommand. Однако ListView остается без изменений; нам по-прежнему нужно определить макет.The ListView, however, remains unchanged; we still need to define its layout. Макет ListView может быть создан вручную с помощью декларативной разметки или из параметра "настроить ListView" в его смарт-теге.The ListView's layout can be constructed manually through its declarative markup or from the "Configure ListView" option in its Smart Tag. Обычно я предпочитаю определять разметку вручную, но использовать любой из самых естественных методов.I usually prefer defining the markup by hand, but use whatever method is most natural to you.

Закончено использование следующих LayoutTemplate, ItemTemplateи ItemSeparatorTemplate для элемента управления ListView:I ended up using the following LayoutTemplate, ItemTemplate, and ItemSeparatorTemplate for my ListView control:

<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.The LayoutTemplate defines the markup emitted by the control, while the ItemTemplate renders each item returned by the SqlDataSource. Результирующая разметка ItemTemplateпомещается в элемент управления itemPlaceholder LayoutTemplate.The ItemTemplate's resulting markup is placed in the LayoutTemplate's itemPlaceholder control. В дополнение к itemPlaceholder``LayoutTemplate включает элемент управления DataPager, который ограничивает ListView отображением всего 10 комментариев гостевой книги на страницу (по умолчанию) и отображает интерфейс разбиения по страницам.In addition to the itemPlaceholder, the LayoutTemplate includes a DataPager control, which limits the ListView to showing just 10 guestbook comments per page (the default) and renders a paging interface.

В моем ItemTemplate Тема комментария к каждой гостевой книге отображается в элементе <h4> с текстом, расположенным под темой.My ItemTemplate displays each guestbook comment's subject in an <h4> element with the body situated below the subject. Обратите внимание, что синтаксис, используемый для отображения текста, принимает данные, возвращаемые инструкцией Eval("Body") DataBinding, преобразует их в строку и заменяет разрывы строк элементом <br />.Note that syntax used for displaying the body takes the data returned by the Eval("Body") databinding statement, converts it to a string, and replaces line breaks with the <br /> element. Это преобразование необходимо для отображения разрывов строк, введенных при отправке комментария, так как в HTML игнорируется пробел.This conversion is needed in order to show the line breaks entered when submitting the comment since whitespace is ignored by HTML. Подпись пользователя отображается под текстом в курсиве, за которым следует домашний город пользователя, ссылка на свою домашнюю страницу, Дата и время внесения комментария, а также имя пользователя, который оставил комментарий.The user's signature is displayed beneath the body in italics, followed by the user's home town, a link to his homepage, the date and time the comment was made, and the username of the person who left the comment.

Уделите время просмотру страницы в браузере.Take a moment to view the page through a browser. Вы должны увидеть комментарии, добавленные в книгу гостевой книги на шаге 5, показанном здесь.You should see the comments that you added to the guestbook in Step 5 displayed here.

книга. aspx теперь отображает комментарии гостевой книгиGuestbook.aspx Now Displays the Guestbook's Comments

Рис. 19. Guestbook.aspx теперь отображает комментарии к гостевой книге (щелкните, чтобы просмотреть изображение с полным размером)Figure 19: Guestbook.aspx Now Displays the Guestbook's Comments (Click to view full-size image)

Попробуйте добавить новый комментарий в гостевую книгу.Try adding a new comment to the guestbook. При нажатии кнопки PostCommentButton страница отправляет обратно, и комментарий добавляется в базу данных, но элемент управления ListView не обновляется для отображения нового комментария.Upon clicking the PostCommentButton button the page posts back and the comment is added to the database, but the ListView control is not updated to show the new comment. Это можно исправить одним из следующих.This can be fixed by either:

  • Обновление обработчика событий Click кнопки PostCommentButton для вызова метода DataBind() элемента управления ListView после вставки нового комментария в базу данных илиUpdating the PostCommentButton button's Click event handler so that it invokes the ListView control's DataBind() method after inserting the new comment into the database, or
  • Присвоение свойству EnableViewState элемента управления ListView значения False.Setting the ListView control's EnableViewState property to False. Этот подход работает потому, что отключение состояния представления элемента управления требует повторной привязки к базовым данным при каждой обратной передаче.This approach works because by disabling the control's view state, it must rebind to the underlying data on every postback.

На веб-сайте учебника, загружаемом из этого руководства, показаны обе методики.The tutorial website downloadable from this tutorial illustrates both techniques. Свойство EnableViewState элемента управления ListView для False и код, необходимый для программной повторной привязки данных к ListView, содержится в обработчике событий Click, но в него добавлен комментарий.The ListView control's EnableViewState property to False and the code needed to programmatically rebind the data to the ListView is present in the Click event handler, but is commented out.

Note

В настоящее время страница AdditionalUserInfo.aspx позволяет пользователю просматривать и изменять параметры домашнего города, домашней страницы и подписи.Currently the AdditionalUserInfo.aspx page allows the user to view and edit their home town, homepage, and signature settings. Может быть неплохо обновить AdditionalUserInfo.aspx, чтобы отобразить комментарии к гостевой книге пользователя, вошедшего в систему.It might be nice to update AdditionalUserInfo.aspx to display the logged in user's guestbook comments. То есть, помимо проверки и изменения сведений, пользователь может посетить страницу AdditionalUserInfo.aspx, чтобы увидеть, какие комментарии в гостевой книге были сделаны в прошлом.That is, in addition to examining and modifying her information, a user can visit the AdditionalUserInfo.aspx page to see what guestbook comments she's made in the past. Я оставлю это в качестве упражнения для заинтересованного читателя.I leave this as an exercise for the interested reader.

Шаг 6. Настройка элемента управления CreateUserWizard для включения интерфейса для домашнего города, домашней страницы и подписиStep 6: Customizing the CreateUserWizard Control to Include an Interface for the Home Town, Homepage, and Signature

SELECT запрос, используемый Guestbook.aspx страницей, использует INNER JOIN для объединения связанных записей между GuestbookComments, UserProfilesи aspnet_Users таблицами.The SELECT query used by the Guestbook.aspx page uses an INNER JOIN to combine the related records amongst the GuestbookComments, UserProfiles, and aspnet_Users tables. Если пользователь без записи в UserProfiles создает комментарий гостевой книги, комментарий не будет отображаться в ListView, так как INNER JOIN возвращает только GuestbookComments записи при наличии совпадающих записей в UserProfiles и aspnet_Users.If a user that has no record in UserProfiles makes a guestbook comment, the comment won't be displayed in the ListView because the INNER JOIN only returns GuestbookComments records when there are matching records in UserProfiles and aspnet_Users. И, как было показано на шаге 3, если у пользователя нет записи в UserProfiles она не может просматривать или изменять ее параметры на странице AdditionalUserInfo.aspx.And as we saw in Step 3, if a user does not have a record in UserProfiles she cannot view or edit her settings in the AdditionalUserInfo.aspx page.

Нет необходимости говорить, что из-за наших решений по проектированию важно, чтобы каждая учетная запись пользователя в системе членства соответствовала записи в таблице UserProfiles.Needless to say, due to our design decisions it is important that every user account in the Membership system have a matching record in the UserProfiles table. Мы хотим, чтобы соответствующая запись была добавлена в UserProfiles всякий раз, когда новая учетная запись пользователя членства создается с помощью CreateUserWizard.What we want is for a corresponding record to be added to UserProfiles whenever a new Membership user account is created through the CreateUserWizard.

Как обсуждалось в учебнике Создание учетных записей пользователей , после создания новой учетной записи членства элемент управления CreateUserWizard вызывает событиеCreatedUser.As discussed in the Creating User Accounts tutorial, after the new Membership user account is created the CreateUserWizard control raises its CreatedUser event. Мы можем создать обработчик событий для этого события, получить UserId для только что созданного пользователя, а затем вставить запись в таблицу UserProfiles со значениями по умолчанию для столбцов HomeTown, HomepageUrlи Signature.We can create an event handler for this event, get the UserId for the just-created user, and then insert a record into the UserProfiles table with default values for the HomeTown, HomepageUrl, and Signature columns. Более того, можно запросить у пользователя эти значения, настроив интерфейс элемента управления CreateUserWizard для включения дополнительных текстовых полей.What's more, it is possible to prompt the user for these values by customizing the CreateUserWizard control's interface to include additional TextBoxes.

Сначала рассмотрим, как добавить новую строку в таблицу UserProfiles в обработчике событий CreatedUser со значениями по умолчанию.Let's first look at how to add a new row to the UserProfiles table in the CreatedUser event handler with default values. После этого будет рассмотрена настройка пользовательского интерфейса элемента управления CreateUserWizard для включения дополнительных полей формы для получения домашнего города, домашней страницы и подписи нового пользователя.Following that, we will see how to customize the CreateUserWizard control's user interface to include additional form fields to collect the new user's home town, homepage, and signature.

Добавление строки по умолчанию вUserProfilesAdding a Default Row toUserProfiles

В учебнике Создание учетных записей пользователей мы добавили элемент управления CreateUserWizard на страницу CreatingUserAccounts.aspx в папке Membership.In the Creating User Accounts tutorial we added a CreateUserWizard control to the CreatingUserAccounts.aspx page in the Membership folder. Чтобы элемент управления CreateUserWizard мог добавить запись a в таблицу UserProfiles при создании учетной записи пользователя, необходимо обновить функциональность элемента управления CreateUserWizard.In order to have the CreateUserWizard control add a record to UserProfiles table upon user account creation, we need to update the CreateUserWizard control's functionality. Вместо того, чтобы вносить эти изменения на странице CreatingUserAccounts.aspx, добавьте новый элемент управления CreateUserWizard на EnhancedCreateUserWizard.aspx страницу и внесите изменения в этом руководстве.Rather than making these changes to the CreatingUserAccounts.aspx page, let's instead add a new CreateUserWizard control to EnhancedCreateUserWizard.aspx page and make the modifications for this tutorial there.

Откройте страницу EnhancedCreateUserWizard.aspx в Visual Studio и перетащите элемент управления CreateUserWizard с панели элементов на страницу.Open the EnhancedCreateUserWizard.aspx page in Visual Studio and drag a CreateUserWizard control from the Toolbox onto the page. Задайте для свойства ID элемента управления CreateUserWizard значение NewUserWizard.Set the CreateUserWizard control's ID property to NewUserWizard. Как мы обсуждали в учебнике Создание учетных записей пользователей , Пользовательский интерфейс по умолчанию CreateUserWizard запрашивает у посетителя необходимые сведения.As we discussed in the Creating User Accounts tutorial, the CreateUserWizard's default user interface prompts the visitor for the necessary information. После того как эти сведения предоставлены, элемент управления создает новую учетную запись пользователя в инфраструктуре членства, не требуя написания единой строки кода.Once this information has been supplied, the control internally creates a new user account in the Membership framework, all without us having to write a single line of code.

Элемент управления CreateUserWizard вызывает ряд событий во время рабочего процесса.The CreateUserWizard control raises a number of events during its workflow. После того, как посетитель предоставит сведения о запросе и отправит форму, элемент управления CreateUserWizard изначально вызывает событиеCreatingUser.After a visitor supplies the request information and submits the form, the CreateUserWizard control initially fires its CreatingUser event. При возникновении проблемы во время процесса создания возникает событиеCreateUserError . Однако если пользователь успешно создан, возникает событиеCreatedUser .If there is a problem during the create process, the CreateUserError event is fired; however, if the user is successfully created, then the CreatedUser event is raised. В учебнике Создание учетных записей пользователей мы создали обработчик события CreatingUser, чтобы убедиться, что заданное имя пользователя не содержит начальных и конечных пробелов и что имя пользователя не отображается в пароле.In the Creating User Accounts tutorial we created an event handler for the CreatingUser event to ensure that the supplied username did not contain any leading or trailing spaces, and that the username did not appear anywhere in the password.

Чтобы добавить строку в таблицу UserProfiles для только что созданного пользователя, необходимо создать обработчик событий для события CreatedUser.In order to add a row in the UserProfiles table for the just-created user, we need to create an event handler for the CreatedUser event. К моменту запуска события CreatedUser учетная запись пользователя уже создана в инфраструктуре членства, что позволяет нам получить значение UserId учетной записи.By the time the CreatedUser event has fired, the user account has already been created in the Membership framework, enabling us to retrieve the account's UserId value.

Создайте обработчик событий для CreatedUser события NewUserWizardи добавьте следующий код:Create an event handler for the NewUserWizard's CreatedUser event and add the following code:

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 только что добавленной учетной записи пользователя.The above code beings by retrieving the UserId of the just-added user account. Это достигается с помощью метода Membership.GetUser(username) для получения сведений о конкретном пользователе, а затем с помощью свойства ProviderUserKey извлекается идентификатор пользователя.This is accomplished by using the Membership.GetUser(username) method to return information about a particular user, and then using the ProviderUserKey property to retrieve their UserId. Имя пользователя, указанное пользователем в элементе управления CreateUserWizard, доступно через свойствоUserName.The username entered by the user in the CreateUserWizard control is available via its UserName property.

Затем строка подключения извлекается из Web.config и указывается инструкция INSERT.Next, the connection string is retrieved from Web.config and the INSERT statement is specified. Создаются экземпляры необходимых объектов ADO.NET и выполняется команда.The necessary ADO.NET objects are instantiated and the command executed. Код назначает DBNull экземпляре для параметров @HomeTown, @HomepageUrlи @Signature, которые влияют на вставку значений базы данных NULL для полей HomeTown, HomepageUrlи Signature.The code assigns a DBNull instance to the @HomeTown, @HomepageUrl, and @Signature parameters, which has the effect of inserting database NULL values for the HomeTown, HomepageUrl, and Signature fields.

Откройте страницу EnhancedCreateUserWizard.aspx в браузере и создайте новую учетную запись пользователя.Visit the EnhancedCreateUserWizard.aspx page through a browser and create a new user account. После этого вернитесь в Visual Studio и изучите содержимое таблиц aspnet_Users и UserProfiles (как мы делали на рис. 12).After doing so, return to Visual Studio and examine the contents of the aspnet_Users and UserProfiles tables (like we did back in Figure 12). Вы должны увидеть новую учетную запись пользователя в aspnet_Users и соответствующую строку UserProfiles (со значениями NULL для HomeTown, HomepageUrlи Signature).You should see the new user account in aspnet_Users and a corresponding UserProfiles row (with NULL values for HomeTown, HomepageUrl, and Signature).

добавлены учетная запись пользователя, и добавлена запись UserProfileA New User Account and UserProfiles Record Have Been Added

Рис. 20. Добавлены новая учетная запись пользователя и запись UserProfiles (щелкните, чтобы просмотреть изображение с полным размером)Figure 20: A New User Account and UserProfiles Record Have Been Added (Click to view full-size image)

После того как посетитель предоставил сведения о новой учетной записи и нащелкнул кнопку "создать пользователя", создается учетная запись пользователя и строка, добавленная в таблицу UserProfiles.After the visitor has supplied his new account information and clicked the "Create User" button, the user account is created and a row added to the UserProfiles table. Затем CreateUserWizard отображает его CompleteWizardStep, в котором отображается сообщение об успешном выполнении и кнопка Continue (продолжить).The CreateUserWizard then displays its CompleteWizardStep, which displays a success message and a Continue button. Нажатие кнопки Продолжить приводит к выполнению обратной передачи, но никакие действия не выполняются, при этом пользователь зависает на странице EnhancedCreateUserWizard.aspx.Clicking the Continue button causes a postback, but no action is taken, leaving the user stuck on the EnhancedCreateUserWizard.aspx page.

Можно указать URL-адрес для отправки пользователю при нажатии кнопки continue через свойствоContinueDestinationPageUrlэлемента управления CreateUserWizard.We can specify a URL to send the user to when the Continue button is clicked via the CreateUserWizard control's ContinueDestinationPageUrl property. Задайте для свойства ContinueDestinationPageUrl значение "~/мембершип/аддитионалусеринфо.аспкс".Set the ContinueDestinationPageUrl property to "~/Membership/AdditionalUserInfo.aspx". После этого новый пользователь будет AdditionalUserInfo.aspx, где он может просматривать и обновлять свои параметры.This takes the new user to AdditionalUserInfo.aspx, where they can view and update their settings.

Настройка интерфейса CreateUserWizard для запроса домашнего города, домашней страницы и подписи нового пользователяCustomizing the CreateUserWizard's Interface to Prompt for the New User's Home Town, Homepage, and Signature

Интерфейс по умолчанию элемента управления CreateUserWizard достаточно для сценариев создания простых учетных записей, где необходимо собирать только основные сведения об учетных записях пользователей, таких как имя пользователя, пароль и электронная почта.The CreateUserWizard control's default interface is sufficient for simple account creation scenarios where only core user account information like username, password, and email need be collected. Но что делать, если мы хотели предложить посетителям ввести домашний город, домашнюю страницу и подпись при создании учетной записи?But what if we wanted to prompt the visitor to enter her home town, homepage, and signature while creating her account? Можно настроить интерфейс элемента управления CreateUserWizard для получения дополнительных сведений при регистрации, и эти сведения можно использовать в обработчике событий CreatedUser для вставки дополнительных записей в основную базу данных.It is possible to customize the CreateUserWizard control's interface to collect additional information at signup, and this information may be used in the CreatedUser event handler to insert additional records into the underlying database.

Элемент управления CreateUserWizard расширяет Управление мастером ASP.NET, то есть элемент управления, позволяющий разработчику страницы определить ряд упорядоченных WizardSteps.The CreateUserWizard control extends the ASP.NET Wizard control, which is a control that allows a page developer to define a series of ordered WizardSteps. Элемент управления мастера визуализирует активный шаг и предоставляет интерфейс навигации, позволяющий посетителю перемещаться по этим шагам.The Wizard control renders the active step and provides a navigation interface that allows the visitor to move through these steps. Элемент управления "Мастер" идеально подходит для разбиения длинной задачи на несколько коротких шагов.The Wizard control is ideal for breaking down a long task into several short steps. Дополнительные сведения об элементе управления Wizard см. в разделе Создание пошагового пользовательского интерфейса с помощью элемента управления мастера ASP.NET 2,0.For more information on the Wizard control, see Creating a Step-by-Step User Interface with the ASP.NET 2.0 Wizard Control.

Разметка по умолчанию элемента управления CreateUserWizard определяет два WizardSteps: CreateUserWizardStep и CompleteWizardStep.The CreateUserWizard control's default markup defines two WizardSteps: CreateUserWizardStep and CompleteWizardStep.

<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, отображает интерфейс, запрашивающий имя пользователя, пароль, адрес электронной почты и т. д.The first WizardStep, CreateUserWizardStep, renders the interface that prompts for the username, password, email, and so on. Когда посетитель предоставит эти сведения и нажмет кнопку "создать пользователя", она отобразится CompleteWizardStep, где отображается сообщение об успешном выполнении и кнопка продолжить.After the visitor supplies this information and clicks "Create User", she is shown the CompleteWizardStep, which shows the success message and a Continue button.

Чтобы настроить интерфейс элемента управления CreateUserWizard для включения дополнительных полей формы, можно:To customize the CreateUserWizard control's interface to include additional form fields, we can:

  • Создайте один или несколько новых WizardStep s, чтобы они содержали дополнительные элементы пользовательского интерфейса.Create one or more newWizardSteps to contain the additional user interface elements. Чтобы добавить новый WizardStep в CreateUserWizard, щелкните ссылку "Добавить/удалить WizardStep s" из смарт-тега, чтобы открыть редактор коллекции WizardStep.To add a new WizardStep to the CreateUserWizard, click the "Add/Remove WizardStep s" link from its Smart Tag to launch the WizardStep Collection Editor. Здесь можно добавить, удалить или изменить порядок шагов в мастере.From there you can add, remove, or reorder the steps in the wizard. Это подход, который мы будем использовать в этом руководстве.This is the approach we will use for this tutorial.

  • Преобразуйте CreateUserWizardStep в редактируемый WizardStep .Convert theCreateUserWizardStepinto an editableWizardStep. Это заменяет CreateUserWizardStep эквивалентом WizardStep, разметка которого определяет пользовательский интерфейс, соответствующий CreateUserWizardStep.This replaces the CreateUserWizardStep with an equivalent WizardStep whose markup defines a user interface that matches the CreateUserWizardStep's. Преобразуя CreateUserWizardStep в WizardStep можно изменить расположение элементов управления или добавить дополнительные элементы пользовательского интерфейса на этот шаг.By converting the CreateUserWizardStep into a WizardStep we can reposition the controls or add additional user interface elements to this step. Чтобы преобразовать CreateUserWizardStep или CompleteWizardStep в редактируемые WizardStep, щелкните ссылку "настроить создание пользователя шага" или "настроить полный шаг" в смарт-теге элемента управления.To convert the CreateUserWizardStep or CompleteWizardStep into an editable WizardStep, click the "Customize Create User Step" or "Customize Complete Step" link from the control's Smart Tag.

  • Используйте сочетание двух приведенных выше параметров.Use some combination of the above two options.

Важно помнить, что элемент управления CreateUserWizard выполняет свой процесс создания учетной записи пользователя при нажатии кнопки "создать пользователя" в его CreateUserWizardStep.One important thing to keep in mind is that the CreateUserWizard control executes its user account creation process when the "Create User" button is clicked from within its CreateUserWizardStep. Не имеет значения, есть ли дополнительные WizardStep s после CreateUserWizardStep или нет.It doesn't matter if there are additional WizardStep s after the CreateUserWizardStep or not.

При добавлении пользовательского WizardStep к элементу управления CreateUserWizard для получения дополнительных пользовательских данных пользовательский WizardStep можно поместить до или после CreateUserWizardStep.When adding a custom WizardStep to the CreateUserWizard control to collect additional user input, the custom WizardStep can be placed before or after the CreateUserWizardStep. Если он находится перед CreateUserWizardStep, то дополнительные входные данные пользователя, собранные из пользовательского WizardStep, доступны для обработчика событий CreatedUser.If it comes before the CreateUserWizardStep then the additional user input collected from the custom WizardStep is available for the CreatedUser event handler. Однако если пользовательская WizardStep находится после CreateUserWizardStep затем на момент отображения настраиваемого WizardStep, Новая учетная запись пользователя уже создана, а событие CreatedUser уже запущено.However, if the custom WizardStep comes after CreateUserWizardStep then by the time the custom WizardStep is displayed the new user account has already been created and the CreatedUser event has already fired.

На рис. 21 показан рабочий процесс, когда добавленный WizardStep предшествует CreateUserWizardStep.Figure 21 shows the workflow when the added WizardStep precedes the CreateUserWizardStep. Поскольку сведения о дополнительных пользователях были собраны в момент срабатывания события CreatedUser, все, что нам нужно сделать, — это обновить обработчик событий CreatedUser, чтобы получить эти входные данные и использовать их для значений параметров инструкции INSERT (а не DBNull.Value).Since the additional user information has been collected by the time the CreatedUser event fires, all we have to do is update the CreatedUser event handler to retrieve these inputs and use those for the INSERT statement's parameter values (rather than DBNull.Value).

рабочий процесс CreateUserWizard, когда дополнительный WizardStep предшествует CreateUserWizardStepThe CreateUserWizard Workflow When an Additional WizardStep Precedes the CreateUserWizardStep

Рис. 21. Рабочий процесс CreateUserWizard, когда дополнительный WizardStep предшествует CreateUserWizardStep (щелкните, чтобы просмотреть изображение с полным размером)Figure 21: The CreateUserWizard Workflow When an Additional WizardStep Precedes the CreateUserWizardStep (Click to view full-size image)

Если пользовательская WizardStep помещается после CreateUserWizardStep, то процесс создания учетной записи пользователя происходит, прежде чем пользователь сможет ввести домашний город, домашнюю страницу или подпись.If the custom WizardStep is placed after the CreateUserWizardStep, however, the create user account process occurs before the user has had a chance to enter her home town, homepage, or signature. В этом случае эти дополнительные сведения необходимо вставить в базу данных после создания учетной записи пользователя, как показано на рис. 22.In such a case, this additional information needs to be inserted into the database after the user account has been created, as Figure 22 illustrates.

рабочий процесс CreateUserWizard, когда после CreateUserWizardStep поступает дополнительный WizardStepThe CreateUserWizard Workflow When an Additional WizardStep Comes After the CreateUserWizardStep

Рис. 22. Рабочий процесс CreateUserWizard, когда после CreateUserWizardStep поступает дополнительный WizardStep (щелкните, чтобы просмотреть изображение с полным размером)Figure 22: The CreateUserWizard Workflow When an Additional WizardStep Comes After the CreateUserWizardStep (Click to view full-size image)

Рабочий процесс, показанный на рис. 22, ожидает вставки записи в таблицу UserProfiles до завершения шага 2.The workflow shown in Figure 22 waits to insert a record into the UserProfiles table until after Step 2 completes. Тем не менее, если посетитель закрывает свой браузер после шага 1, мы достигают состояния, в котором была создана учетная запись пользователя, но запись не была добавлена в UserProfiles.If the visitor closes her browser after step 1, however, we will have reached a state where a user account was created, but no record was added to UserProfiles. Одним из возможных решений является запись со NULL или значениями по умолчанию, вставленными в UserProfiles в обработчике событий CreatedUser (который срабатывает после шага 1), а затем обновляет эту запись после завершения шага 2.One workaround is to have a record with NULL or default values inserted into UserProfiles in the CreatedUser event handler (which fires after step 1), and then update this record after step 2 completes. Это гарантирует, что запись UserProfiles будет добавлена для учетной записи пользователя, даже если пользователь завершает процесс регистрации с самого посредине.This ensures that a UserProfiles record will be added for the user account even if the user quits the registration process midway through.

В этом руководстве мы создадим новый WizardStep, который будет выполняться после CreateUserWizardStep, но перед CompleteWizardStep.For this tutorial let's create a new WizardStep that occurs after the CreateUserWizardStep but before the CompleteWizardStep. Давайте сначала создадим WizardStep на месте и настроили, а затем рассмотрим код.Let's first get the WizardStep in place and configured and then we'll look at the code.

В смарт-теге элемента управления CreateUserWizard выберите "Добавить/удалить WizardStep s", который открывает диалоговое окно Редактор коллекции WizardStep.From the CreateUserWizard control's Smart Tag, select the "Add/Remove WizardStep s", which brings up the WizardStep Collection Editor dialog. Добавьте новый WizardStep, задав для его ID значение UserSettings, Title для параметров и StepType.StepAdd a new WizardStep, setting its ID to UserSettings, its Title to "Your Settings" and its StepType to Step. Затем поместите его таким образом, чтобы он поступил после CreateUserWizardStep ("зарегистрироваться для создания новой учетной записи") и до CompleteWizardStep ("Complete"), как показано на рис. 23.Then position it so that it comes after the CreateUserWizardStep ("Sign Up for Your New Account") and before the CompleteWizardStep ("Complete"), as shown in Figure 23.

добавить новый WizardStep в элемент управления CreateUserWizardAdd a New WizardStep to the CreateUserWizard Control

Рис. 23. добавление нового WizardStep в элемент управления CreateUserWizard (щелкните, чтобы просмотреть изображение с полным размером)Figure 23: Add a New WizardStep to the CreateUserWizard Control (Click to view full-size image)

Нажмите кнопку ОК, чтобы закрыть диалоговое окно Редактор коллекции WizardStep.Click OK to close the WizardStep Collection Editor dialog. Новый WizardStep свидетельствует обновленная декларативная разметка элемента управления CreateUserWizard:The new WizardStep is evidenced by the CreateUserWizard control's updated declarative markup:

<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>.Note the new <asp:WizardStep> element. Чтобы получить домашний город, домашнюю страницу и подпись нового пользователя, необходимо добавить пользовательский интерфейс.We need to add the user interface to collect the new user's home town, homepage, and signature here. Это содержимое можно ввести в декларативном синтаксисе или в конструкторе.You can enter this content in the declarative syntax or through the Designer. Чтобы использовать конструктор, выберите в раскрывающемся списке в смарт-теге шаг "ваши параметры", чтобы просмотреть шаг в конструкторе.To use the Designer, select the "Your Settings" step from the drop-down list in the Smart Tag to see the step in the Designer.

Note

При выборе шага в раскрывающемся списке смарт-тега обновляется свойствоActiveStepIndexэлемента управления CreateUserWizard, которое указывает индекс начального шага.Selecting a step through the Smart Tag's drop-down list updates the CreateUserWizard control's ActiveStepIndex property, which specifies the index of the starting step. Поэтому, если вы используете этот раскрывающийся список для изменения шага "ваши параметры" в конструкторе, убедитесь, что для него установлен флажок "зарегистрироваться для использования новой учетной записи", чтобы этот шаг отображался при первом посещении пользователем страницы EnhancedCreateUserWizard.aspx.Therefore, if you use this drop-down list to edit the "Your Settings" step in the Designer, be sure to set it back to "Sign Up for Your New Account" so that this step is shown when users first visit the EnhancedCreateUserWizard.aspx page.

Создайте пользовательский интерфейс на шаге "Параметры", который содержит три элемента управления TextBox с именами HomeTown, HomepageUrlи Signature.Create a user interface within the "Your Settings" step that contains three TextBox controls named HomeTown, HomepageUrl, and Signature. После создания этого интерфейса декларативная разметка CreateUserWizard должна выглядеть следующим образом:After constructing this interface, the CreateUserWizard's declarative markup should look similar to the following:

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

Откройте эту страницу в браузере и создайте новую учетную запись пользователя, указав значения для домашнего города, домашней страницы и подписи.Go ahead and visit this page through a browser and create a new user account, specifying values for the home town, homepage, and signature. После завершения CreateUserWizardStep учетная запись пользователя создается в инфраструктуре членства и запускается обработчик событий CreatedUser, который добавляет новую строку для UserProfiles, но с NULL базы данных для HomeTown, HomepageUrlи Signature.After completing the CreateUserWizardStep the user account is created in the Membership framework and the CreatedUser event handler runs, which adds a new row to UserProfiles, but with a database NULL value for HomeTown, HomepageUrl, and Signature. Значения, указанные для домашнего города, домашней страницы и подписи, никогда не используются.The values entered for the home town, homepage, and signature are never used. В результате получается новая учетная запись пользователя с записью UserProfiles, для которой еще не заданы поля HomeTown, HomepageUrlи Signature.The net result is a new user account with a UserProfiles record whose HomeTown, HomepageUrl, and Signature fields have yet to be specified.

Необходимо выполнить код после шага "ваши параметры", который принимает значения домашнего города, хонепаже и сигнатуры, указанные пользователем, и обновляет соответствующую запись UserProfiles.We need to execute code after the "Your Settings" step that takes the home town, honepage, and signature values entered by the user and updates the appropriate UserProfiles record. При каждом перемещении пользователя между шагами в элементе управления мастера срабатывает событиеActiveStepChanged мастера.Each time the user moves between steps in a Wizard control, the Wizard's ActiveStepChanged event fires. Мы можем создать обработчик событий для этого события и обновить таблицу UserProfiles после завершения этапа "Параметры".We can create an event handler for this event and update the UserProfiles table when the "Your Settings" step has completed.

Добавьте обработчик событий для события ActiveStepChanged CreateUserWizard и добавьте следующий код:Add an event handler for the CreateUserWizard's ActiveStepChanged event and add the following code:

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

Приведенный выше код начинается с определения того, был ли достигнут шаг "завершено".The above code starts by determining if we have just reached the "Complete" step. Так как действие "завершено" происходит сразу после этапа "Параметры", когда посетитель достигает «завершенного» шага, это означает, что он только что завершил действие «параметры».Since the "Complete" step occurs immediately after the "Your Settings" step, then when the visitor reaches "Complete" step that means she just finished the "Your Settings" step.

В этом случае нам нужно программно ссылаться на элементы управления TextBox в UserSettings WizardStep.In such a case, we need to programmatically reference the TextBox controls within the UserSettings WizardStep. Для этого сначала используется метод FindControl для программной ссылки на UserSettings WizardStep, а затем снова сослаться на текстовые поля из WizardStep.This is accomplished by first using the FindControl method to programmatically referencing the UserSettings WizardStep, and then again to reference the TextBoxes from within the WizardStep. После ссылки на текстовые поля можно приступить к выполнению инструкции UPDATE.Once the TextBoxes have been referenced, we're ready to execute the UPDATE statement. UPDATEная инструкция имеет то же количество параметров, что и инструкция INSERT в обработчике событий CreatedUser, но здесь мы используем значения домашнего города, домашней страницы и подписи, предоставленные пользователем.The UPDATE statement has the same number of parameters as the INSERT statement in the CreatedUser event handler, but here we use the home town, homepage, and signature values supplied by the user.

После создания этого обработчика событий перейдите на страницу EnhancedCreateUserWizard.aspx в браузере и создайте новую учетную запись пользователя, указав значения для домашнего города, домашней страницы и подписи.With this event handler in place, visit the EnhancedCreateUserWizard.aspx page through a browser and create a new user account specifying values for the home town, homepage, and signature. После создания новой учетной записи необходимо перенаправить на страницу AdditionalUserInfo.aspx, где отображаются только что введенные домашний город, Домашняя страница и подпись.After creating the new account you should be redirected to the AdditionalUserInfo.aspx page, where the just-entered home town, homepage, and signature information is displayed.

Note

В настоящее время наш веб-сайт содержит две страницы, на которых посетитель может создать новую учетную запись: CreatingUserAccounts.aspx и EnhancedCreateUserWizard.aspx.Our website currently has two pages from which a visitor can create a new account: CreatingUserAccounts.aspx and EnhancedCreateUserWizard.aspx. Страница веб-сайта и имя входа указывают на страницу CreatingUserAccounts.aspx, но страница CreatingUserAccounts.aspx не запрашивает у пользователя домашний город, домашнюю страницу и сведения о подписи и не добавляет соответствующую строку в UserProfiles.The website's sitemap and login page point to the CreatingUserAccounts.aspx page, but the CreatingUserAccounts.aspx page does not prompt the user for their home town, homepage, and signature information and does not add a corresponding row to UserProfiles. Поэтому обновите страницу CreatingUserAccounts.aspx таким образом, чтобы она предложит эту функцию, или обновите карту сайта и страницу входа в справочные EnhancedCreateUserWizard.aspx вместо CreatingUserAccounts.aspx.Therefore, either update the CreatingUserAccounts.aspx page so that it offers this functionality or update the sitemap and login page to reference EnhancedCreateUserWizard.aspx instead of CreatingUserAccounts.aspx. При выборе второго варианта не забудьте обновить файл Web.config папки Membership, чтобы разрешить анонимным пользователям доступ к странице EnhancedCreateUserWizard.aspx.If you choose the latter option, be sure to update the Membership folder's Web.config file so as to allow anonymous users access to the EnhancedCreateUserWizard.aspx page.

СводкаSummary

В этом учебнике мы рассматривали методы моделирования данных, связанных с учетными записями пользователей в инфраструктуре членства.In this tutorial we looked at techniques for modeling data that is related to user accounts within the Membership framework. В частности, мы рассматривали моделирование сущностей, которые совместно используют связь «один ко многим» с учетными записями пользователей, а также с данными, которые совместно используют связь «один к одному».In particular, we looked at modeling entities that share a one-to-many relationship with user accounts as well as data that shares a one-to-one relationship. Кроме того, мы увидели, как можно отобразить, вставить и обновить эту связанную информацию, с некоторыми примерами с помощью элемента управления SqlDataSource и других пользователей, использующих код ADO.NET.Furthermore, we saw how this related information could be displayed, inserted, and updated, with some examples using the SqlDataSource control and others using ADO.NET code.

Этот учебник завершает наш взгляд на учетные записи пользователей.This tutorial completes our look at user accounts. Начиная со следующего учебного курса, мы будем приносим внимание к ролям.Starting with the next tutorial we will turn our attention to roles. В следующих нескольких учебных курсах рассматривается инфраструктура ролей, приведены инструкции по созданию ролей, назначению ролей пользователям, определению ролей, к которым принадлежит пользователь, и применению авторизации на основе ролей.Over the next several tutorials we will look at the Roles framework, see how to create new roles, how to assign roles to users, how to determine what roles a user belongs to, and how to apply role-based authorization.

Поздравляем с программированием!Happy Programming!

Дополнительные материалыFurther Reading

Дополнительные сведения о разделах, обсуждаемых в этом руководстве, см. в следующих ресурсах:For more information on the topics discussed in this tutorial, refer to the following resources:

Об автореAbout the Author

Скотт Митчелл, автор нескольких книг по ASP/ASP. NET и основатель 4GuysFromRolla.com, работал с веб-технологиями Майкрософт с 1998.Scott Mitchell, author of multiple ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Скотт работает как независимый консультант, преподаватель и модуль записи.Scott works as an independent consultant, trainer, and writer. Его последняя книга — Sams обучать себя ASP.NET 2,0 за 24 часа .His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Скотт можно получить по адресу mitchell@4guysfromrolla.com или через свой блог по адресу http://ScottOnWriting.NET.Scott can be reached at mitchell@4guysfromrolla.com or via his blog at http://ScottOnWriting.NET.

Особая благодарность...Special Thanks To…

Эта серия руководств была рассмотрена многими полезными рецензентами.This tutorial series was reviewed by many helpful reviewers. Хотите ознакомиться с моими будущими статьями MSDN?Interested in reviewing my upcoming MSDN articles? Если это так, расположите строку в mitchell@4GuysFromRolla.com.If so, drop me a line at mitchell@4GuysFromRolla.com.