Сохранение дополнительных сведений о пользователе (C#)
Примечание
С момента написания этой статьи поставщики членства ASP.NET были заменены ASP.NET Identity. Мы настоятельно рекомендуем обновить приложения для использования платформы ASP.NET Identity , а не поставщиков членства, которые были представлены на момент написания этой статьи. ASP.NET Identity имеет ряд преимуществ по сравнению с системой членства ASP.NET, в том числе :
- более высокая производительность;
- Улучшенная расширяемость и тестируемость
- Поддержка OAuth, OpenID Connect и двухфакторной проверки подлинности
- Поддержка удостоверений на основе утверждений
- Улучшенное взаимодействие с ASP.Net Core
Скачать код или скачать PDF-файл
В этом руководстве мы ответим на этот вопрос, создав очень зачаточные приложения гостевой книги. При этом мы рассмотрим различные варианты моделирования сведений о пользователях в базе данных, а затем узнаем, как связать эти данные с учетными записями пользователей, созданными платформой членства.
Введение
ASP. Платформа членства NET предлагает гибкий интерфейс для управления пользователями. API членства включает методы проверки учетных данных, получения сведений о вошедшего в систему пользователя, создания новой учетной записи пользователя и удаления учетной записи пользователя. Каждая учетная запись пользователя на платформе членства содержит только свойства, необходимые для проверки учетных данных и выполнения важных задач, связанных с учетной записью пользователя. Об этом свидетельствуют методы и свойства MembershipUser
класса , который моделирует учетную запись пользователя на платформе членства. Этот класс имеет свойства, такие как UserName
, Email
и IsLockedOut
, и методы, такие как GetPassword
и UnlockUser
.
Часто приложениям требуется хранить дополнительные сведения о пользователях, не включенные в платформу членства. Например, интернет-магазину может потребоваться разрешить каждому пользователю хранить адреса доставки и выставления счетов, платежные сведения, предпочтения доставки и контактный номер телефона. Кроме того, каждый заказ в системе связан с определенной учетной записью пользователя.
Класс MembershipUser
не включает такие свойства, как PhoneNumber
или DeliveryPreferences
.PastOrders
Как же отслеживать сведения о пользователе, необходимые приложению, и интегрировать их с платформой членства? В этом руководстве мы ответим на этот вопрос, создав очень зачаточные приложения гостевой книги. При этом мы рассмотрим различные варианты моделирования сведений о пользователях в базе данных, а затем узнаем, как связать эти данные с учетными записями пользователей, созданными платформой членства. Приступим к работе!
Шаг 1. Создание модели данных приложения Гостевой книги
Существует множество методов, которые можно использовать для сбора сведений о пользователях в базе данных и их связывания с учетными записями пользователей, созданными платформой членства. Чтобы проиллюстрировать эти методы, необходимо дополнить учебное веб-приложение, чтобы оно записывало какие-то данные, связанные с пользователями. (В настоящее время модель данных приложения содержит только таблицы служб приложений, необходимые для SqlMembershipProvider
.)
Давайте создадим очень простое приложение гостевой книги, в котором пользователь, прошедший проверку подлинности, может оставить комментарий. В дополнение к хранению комментариев гостевой книги, давайте разрешим каждому пользователю хранить свой родной город, домашнюю страницу и подпись. Если это указано, то родной город, домашняя страница и подпись пользователя будут отображаться в каждом сообщении, оставленном в гостевой книге.
GuestbookComments
Добавление таблицы
Чтобы записать комментарии гостевой книги, необходимо создать таблицу базы данных с именем GuestbookComments
, которая содержит такие столбцы, как CommentId
, Subject
, Body
и CommentDate
. Нам также нужно, чтобы каждая запись в GuestbookComments
таблице ссылались на пользователя, который оставил комментарий.
Чтобы добавить эту таблицу в базу данных, перейдите к Обозреватель базы данных в Visual Studio и изучите SecurityTutorials
базу данных. Щелкните правой кнопкой мыши папку Таблицы и выберите команду Добавить новую таблицу. Откроется интерфейс, позволяющий определить столбцы для новой таблицы.
Рис. 1. Добавление новой таблицы в SecurityTutorials
базу данных (щелкните для просмотра полноразмерного изображения)
Затем определите GuestbookComments
столбцы . Начните с добавления столбца с именем CommentId
типа uniqueidentifier
. Этот столбец будет уникальным образом идентифицировать каждый комментарий в гостевой книге, поэтому запретить NULL
s и пометить его как первичный ключ таблицы. Вместо того чтобы указывать значение для CommentId
поля в каждом INSERT
, можно указать, что новое uniqueidentifier
значение должно быть автоматически создано для этого поля в , INSERT
задав для столбца значение NEWID()
по умолчанию . После добавления этого первого поля, помечая его как первичный ключ и задав его значение по умолчанию, ваш экран должен выглядеть так же, как на снимке экрана, показанном на рисунке 2.
Рис. 2. Добавление основного столбца с именем CommentId
(щелкните для просмотра полноразмерного изображения)
Затем добавьте столбец с именем Subject
типа nvarchar(50)
и столбец с именем Body
типа nvarchar(MAX)
, запретив NULL
s в обоих столбцах. После этого добавьте столбец с именем CommentDate
типа datetime
. Запретить NULL
и задать CommentDate
для столбца значение getdate()
по умолчанию .
Остается только добавить столбец, который связывает учетную запись пользователя с каждым комментарием гостевой книги. Одним из вариантов является добавление столбца с именем UserName
типа nvarchar(256)
. Это подходящий вариант при использовании поставщика членства, отличного от SqlMembershipProvider
. Но при использовании SqlMembershipProvider
, как это описано в этой серии руководств, UserName
столбец в aspnet_Users
таблице не гарантируется, что он будет уникальным. Первичный aspnet_Users
ключ таблицы имеет UserId
тип uniqueidentifier
. Поэтому для GuestbookComments
таблицы требуется столбец с именем UserId
типа uniqueidentifier
(запретить NULL
значения). Добавьте этот столбец.
Примечание
Как мы обсуждали в учебнике Создание схемы членства в SQL Server, платформа членства предназначена для предоставления нескольким веб-приложениям с разными учетными записями пользователей совместно использовать одно и то же хранилище пользователей. Это делается путем секционирования учетных записей пользователей по разным приложениям. И хотя каждое имя пользователя гарантированно будет уникальным в пределах приложения, одно и то же имя пользователя может использоваться в разных приложениях, использующих одно и то же хранилище пользователей. В таблице есть составное UNIQUE
ограничение aspnet_Users
для UserName
полей и ApplicationId
, но не для одного UserName
только поля. Следовательно, в таблице aspnet_Users может быть две (или более) записи с одинаковым UserName
значением. Однако UNIQUE
есть ограничение на aspnet_Users
поле таблицы UserId
(так как оно является первичным ключом). Ограничение UNIQUE
важно, так как без него невозможно установить ограничение внешнего ключа между GuestbookComments
таблицами и aspnet_Users
.
После добавления столбца UserId
сохраните таблицу, щелкнув значок Сохранить на панели инструментов. Назовите новую таблицу GuestbookComments
.
У нас есть последняя проблема с таблицей GuestbookComments
: необходимо создать ограничение внешнего ключа между столбцом GuestbookComments.UserId
и столбцом aspnet_Users.UserId
. Для этого щелкните значок Связь на панели инструментов, чтобы открыть диалоговое окно Связи внешних ключей. (Кроме того, можно запустить это диалоговое окно, перейдя в меню Таблица Designer и выбрав Связи.)
Нажмите кнопку Добавить в левом нижнем углу диалогового окна Связи внешних ключей. Это добавит новое ограничение внешнего ключа, хотя нам по-прежнему нужно определить таблицы, участвующие в связи.
Рис. 3. Использование диалогового окна "Связи внешних ключей" для управления ограничениями внешнего ключа таблицы (щелкните для просмотра полноразмерного изображения)
Затем щелкните значок с многоточием в строке "Спецификации таблиц и столбцов" справа. Откроется диалоговое окно Таблицы и столбцы, в котором можно указать таблицу и столбец первичного GuestbookComments
ключа, а также столбец внешнего ключа из таблицы. В частности, выберите aspnet_Users
и UserId
в качестве таблицы и столбца первичного GuestbookComments
ключа, а UserId
в таблице — столбец внешнего ключа (см. рис. 4). Определив таблицы и столбцы первичного и внешнего ключей, нажмите кнопку ОК, чтобы вернуться в диалоговое окно Связи внешних ключей.
Рис. 4. Установка ограничения внешнего ключа между aspnet_Users
таблицами и GuesbookComments
(щелкните для просмотра полноразмерного изображения)
На этом этапе установлено ограничение внешнего ключа. Наличие этого ограничения обеспечивает реляционную целостность между двумя таблицами, гарантируя, что запись гостевой книги никогда не будет ссылаться на несуществующую учетную запись пользователя. По умолчанию ограничение внешнего ключа запрещает удаление родительской записи при наличии соответствующих дочерних записей. То есть, если пользователь делает один или несколько комментариев гостевой книги, а затем мы попытаемся удалить ее учетную запись, удаление завершится ошибкой, если его комментарии гостевой книги не будут удалены первым.
Ограничения внешнего ключа можно настроить для автоматического удаления связанных дочерних записей при удалении родительской записи. Другими словами, мы можем настроить это ограничение внешнего ключа, чтобы записи гостевой книги пользователя автоматически удалялись при удалении учетной записи пользователя. Для этого разверните раздел "Спецификация INSERT and UPDATE" и задайте для свойства "Удалить правило" значение Каскад.
Рис. 5. Настройка ограничения внешнего ключа для каскадных удалений (щелкните для просмотра полноразмерного изображения)
Чтобы сохранить ограничение внешнего ключа, нажмите кнопку Закрыть, чтобы выйти из связи внешнего ключа. Затем щелкните значок Сохранить на панели инструментов, чтобы сохранить таблицу и эту связь.
Хранение домашней страницы, домашней страницы и подписи пользователя
В GuestbookComments
таблице показано, как хранить информацию, которая использует отношение "один ко многим" с учетными записями пользователей. Так как каждая учетная запись пользователя может иметь произвольное количество связанных комментариев, эта связь моделировается путем создания таблицы для хранения набора примечаний, включающего столбец, который связывает каждый комментарий с конкретным пользователем. При использовании SqlMembershipProvider
эту связь лучше всего установить, создав столбец с именем UserId
типа uniqueidentifier
и ограничение внешнего ключа между этим столбцом и aspnet_Users.UserId
.
Теперь нам нужно связать три столбца с каждой учетной записью пользователя, чтобы сохранить родной город, домашнюю страницу и подпись пользователя, которые будут отображаться в комментариях к гостевой книге. Это можно сделать несколькими способами.
Добавление новых столбцов в
aspnet_Users
Илиaspnet_Membership
Таблицы. Я бы не рекомендовал этот подход, так как он изменяет схему, используемую .SqlMembershipProvider
Это решение может вернуться, чтобы преследовать вас вниз по дороге. Например, что делать, если в будущей версии ASP.NET используется другаяSqlMembershipProvider
схема. Корпорация Майкрософт может включить средство для переноса данных ASP.NET 2.0SqlMembershipProvider
в новую схему, но если вы изменили схему ASP.NET 2.0SqlMembershipProvider
, такое преобразование может оказаться невозможным.Используйте ASP. Платформа профилей NET, определяющая свойство профиля для родного города, домашней страницы и подписи. ASP.NET включает платформу профилей, предназначенную для хранения дополнительных пользовательских данных. Как и платформа членства, платформа профилей создается на основе модели поставщика. Платформа .NET Framework поставляется с
SqlProfileProvider
sthat хранит данные профиля в базе данных SQL Server. Фактически в базе данных уже есть таблица, используемаяSqlProfileProvider
(aspnet_Profile
), так как она была добавлена при добавлении служб приложений в учебнике Создание схемы членства в SQL Server.
Main преимущество платформы профилей заключается в том, что она позволяет разработчикам определять свойства профиля вWeb.config
. Не нужно писать код для сериализации данных профиля в базовое хранилище данных и из него. Короче говоря, невероятно легко определить набор свойств профиля и работать с ними в коде. Однако система профилей оставляет желать лучшего, когда дело доходит до управления версиями, поэтому если у вас есть приложение, в которое вы ожидаете, что позже будут добавлены новые пользовательские свойства или существующие свойства будут удалены или изменены, то платформа профилей может быть не лучшим вариантом. Кроме того, свойстваSqlProfileProvider
профиля хранятся в строго денормализованном режиме, что делает практически невозможным выполнение запросов непосредственно к данным профиля (например, количество пользователей в родном городе Нью-йорк).
Дополнительные сведения о платформе профилей см. в разделе "Дополнительные сведения" в конце этого руководства.Добавьте эти три столбца в новую таблицу в базе данных и установите связь "один к одному" между этой таблицей и
aspnet_Users
. Этот подход включает в себя немного больше работы, чем с платформой профилей, но обеспечивает максимальную гибкость в модели дополнительных свойств пользователей в базе данных. Это параметр, который мы будем использовать в этом руководстве.
Мы создадим таблицу с именем UserProfiles
, чтобы сохранить родной город, домашнюю страницу и подпись для каждого пользователя. Щелкните правой кнопкой мыши папку Таблицы в окне Обозреватель базы данных и выберите создать таблицу. Присвойте первому столбцу UserId
uniqueidentifier
имя и задайте для его типа значение . Запретить NULL
значения и пометить столбец как первичный ключ. Затем добавьте столбцы с именами: HomeTown
типа nvarchar(50)
; HomepageUrl
типа nvarchar(100)
; и сигнатура типа nvarchar(500)
. Каждый из этих трех столбцов может принимать NULL
значение.
Рис. 6. Создание UserProfiles
таблицы (щелкните для просмотра полноразмерного изображения)
Сохраните таблицу и назовите ее UserProfiles
. Наконец, установите ограничение внешнего ключа между полем UserProfiles
UserId
таблицы и полем aspnet_Users.UserId
. Как и в случае с ограничением внешнего ключа между GuestbookComments
таблицами и aspnet_Users
, это ограничение каскадно удаляет. UserId
Так как поле в UserProfiles
является первичным ключом, это гарантирует, что в UserProfiles
таблице будет не более одной записи для каждой учетной записи пользователя. Этот тип связи называется "один к одному".
Теперь, когда у нас есть модель данных, мы готовы использовать ее. На шагах 2 и 3 мы рассмотрим, как вошедший в систему пользователь может просматривать и изменять сведения о родном городе, домашней странице и подписи. На шаге 4 мы создадим интерфейс для пользователей, прошедших проверку подлинности, для отправки новых комментариев в гостевую книгу и просмотра существующих.
Шаг 2. Отображение родного города пользователя, домашней страницы и подписи
Существует множество способов, позволяющих вошедшего в систему пользователя просматривать и изменять свой родной город, домашнюю страницу и сведения о подписях. Можно вручную создать пользовательский интерфейс с элементами управления TextBox и Label или использовать один из веб-элементов управления данными, например Элемент управления DetailsView. Чтобы выполнить базу данных SELECT
и UPDATE
инструкции, можно написать ADO.NET код в классе кода программной части страницы или использовать декларативный подход с SqlDataSource. В идеале наше приложение должно содержать многоуровневую архитектуру, которую можно вызвать программным способом из класса кода программной части страницы или декларативно с помощью элемента управления ObjectDataSource.
Так как эта серия руководств посвящена проверке подлинности на основе форм, авторизации, учетным записям пользователей и ролям, подробного обсуждения этих различных вариантов доступа к данным и причин, почему многоуровневая архитектура предпочтительнее, чем выполнение инструкций SQL непосредственно на странице ASP.NET. Я собираюсь ознакомиться с использованием DetailsView и SqlDataSource — самого быстрого и простого варианта, но обсуждаемые понятия, безусловно, можно применить к альтернативным веб-элементам управления и логике доступа к данным. Дополнительные сведения о работе с данными в ASP.NET см. в статье Работа с данными в ASP.NET 2.0 .
Откройте страницу в папке Membership
и добавьте элемент управления DetailsView на страницу, задав для его ID
свойства значение UserProfile
и очистив его Width
свойства и Height
.AdditionalUserInfo.aspx
Разверните смарт-тег DetailsView и привяжите его к новому элементу управления источником данных. Откроется мастер настройки DataSource (см. рис. 7). На первом шаге необходимо указать тип источника данных. Так как мы собираемся подключиться напрямую к SecurityTutorials
базе данных, щелкните значок База данных, указав в ID
качестве UserProfileDataSource
.
Рис. 7. Добавление нового элемента управления SqlDataSource с именем UserProfileDataSource
(щелкните для просмотра полноразмерного изображения)
На следующем экране появится запрос на использование базы данных. Мы уже определили строку подключения в Web.config
для SecurityTutorials
базы данных. Это имя строки подключения — SecurityTutorialsConnectionString
должно находиться в раскрывающемся списке. Выберите этот параметр и нажмите кнопку Далее.
Рис. 8. Выбор SecurityTutorialsConnectionString
из списка Drop-Down (щелкните, чтобы просмотреть полноразмерное изображение)
На следующем экране нам будет предлагаться указать таблицу и столбцы для запроса. Выберите таблицу UserProfiles
из раскрывающегося списка и проверка все столбцы.
Рис. 9. Возврат всех столбцов из UserProfiles
таблицы (щелкните для просмотра полноразмерного изображения)
Текущий запрос на рис. 9 возвращает все записи в UserProfiles
, но нас интересует только текущая запись пользователя. Чтобы добавить WHERE
предложение, нажмите кнопку WHERE
, чтобы открыть диалоговое окно Добавление WHERE
предложения (см. рис. 10). Здесь можно выбрать столбец для фильтрации, оператор и источник параметра фильтра. Выберите UserId
в качестве столбца и "=" в качестве оператора.
К сожалению, нет встроенного источника параметров для возврата значения текущего UserId
вошедшего в систему пользователя. Нам потребуется захватить это значение программным способом. Поэтому задайте для раскрывающегося списка Источник значение Нет, нажмите кнопку Добавить, чтобы добавить параметр, а затем нажмите кнопку ОК.
Рис. 10. Добавление параметра фильтра в UserId
столбец (щелкните для просмотра полноразмерного изображения)
После нажатия кнопки ОК вы вернеться на экран, показанный на рис. 9. Однако на этот раз SQL-запрос в нижней части экрана должен содержать WHERE
предложение . Нажмите кнопку Далее, чтобы перейти к экрану "Тестовый запрос". Здесь можно выполнить запрос и просмотреть результаты. Чтобы завершить работу мастера, нажмите кнопку Готово.
После завершения работы мастера настройки DataSource Visual Studio создает элемент управления SqlDataSource на основе параметров, указанных в мастере. Кроме того, он вручную добавляет BoundFields в DetailsView для каждого столбца, возвращаемого sqlDataSource SelectCommand
. Нет необходимости отображать UserId
поле в DetailsView, так как пользователю не нужно знать это значение. Это поле можно удалить непосредственно из декларативной разметки элемента управления DetailsView или щелкнув ссылку "Изменить поля" в смарт-теге.
На этом этапе декларативная разметка страницы должна выглядеть примерно так:
<asp:DetailsView ID="UserProfile" runat="server"
AutoGenerateRows="False" DataKeyNames="UserId"
DataSourceID="UserProfileDataSource">
<Fields>
<asp:BoundField DataField="HomeTown" HeaderText="HomeTown"
SortExpression="HomeTown" />
<asp:BoundField DataField="HomepageUrl" HeaderText="HomepageUrl"
SortExpression="HomepageUrl" />
<asp:BoundField DataField="Signature" HeaderText="Signature"
SortExpression="Signature" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="UserProfileDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:SecurityTutorialsConnectionString %>"
SelectCommand="SELECT [UserId], [HomeTown], [HomepageUrl], [Signature] FROM
[UserProfiles] WHERE ([UserId] = @UserId)">
<SelectParameters>
<asp:Parameter Name="UserId" Type="Object" />
</SelectParameters>
</asp:SqlDataSource>
Перед выбором данных необходимо программно задать для параметра элемента управления UserId
SqlDataSource значение текущего пользователя UserId
, выполнившего вход. Это можно сделать, создав обработчик событий для события SqlDataSource Selecting
и добавив в него следующий код:
protected void UserProfileDataSource_Selecting(object sender,
SqlDataSourceSelectingEventArgs e)
{
// Get a reference to the currently logged on user
MembershipUser currentUser = Membership.GetUser();
// Determine the currently logged on user's UserId value
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
// Assign the currently logged on user's UserId to the @UserId parameter
e.Command.Parameters["@UserId"].Value = currentUserId;
}
Приведенный выше код начинается с получения ссылки на текущего пользователя, выполнившего вход в систему, путем вызова Membership
метода класса GetUser
. MembershipUser
Возвращает объект , свойство которого ProviderUserKey
содержит UserId
объект . Затем UserId
значение присваивается параметру SqlDataSource @UserId
.
Примечание
Метод Membership.GetUser()
возвращает сведения о вошедшего в систему пользователя. Если анонимный пользователь посещает страницу, он возвращает значение null
. В этом случае при попытке чтения свойства в следующей строке ProviderUserKey
кода будет NullReferenceException
возникать . Конечно, нам не нужно беспокоиться о Membership.GetUser()
возврате null
значения на странице, так как мы настроили авторизацию URL-адреса в AdditionalUserInfo.aspx
предыдущем руководстве, чтобы только прошедшие проверку подлинности пользователи могли получить доступ к ASP.NET ресурсам в этой папке. Если вам нужно получить доступ к сведениям о вошедшего в систему пользователя на странице, на которой разрешен анонимный доступ, перед ссылкой на его свойства обязательно проверка, что из метода возвращается объект, отличныйnull MembershipUser
от GetUser()
объекта .
Если вы перейдете на страницу AdditionalUserInfo.aspx
через браузер, вы увидите пустую страницу, так как мы еще не добавили строки в таблицу UserProfiles
. На шаге 6 мы рассмотрим, как настроить элемент управления CreateUserWizard для автоматического добавления новой строки в UserProfiles
таблицу при создании новой учетной записи пользователя. Однако сейчас необходимо вручную создать запись в таблице.
Перейдите к Обозреватель базы данных в Visual Studio и разверните папку Таблицы. Щелкните таблицу правой aspnet_Users
кнопкой мыши и выберите пункт "Показать данные таблицы", чтобы просмотреть записи в таблице. Сделайте то же самое для UserProfiles
таблицы. На рисунке 11 показаны эти результаты при вертикальном расположении плитки. В моей базе данных в настоящее aspnet_Users
время есть записи для Брюса, Фреда и Тито, но нет записей в UserProfiles
таблице.
Рис. 11. Содержимое aspnet_Users
и UserProfiles
таблицы отображаются (щелкните для просмотра полноразмерного изображения)
Добавьте новую запись в таблицу UserProfiles
, вручную введя значения для HomeTown
полей , HomepageUrl
и Signature
. Самый простой способ получить допустимое UserId
значение в новой UserProfiles
записи — выбрать UserId
поле из определенной учетной записи пользователя в aspnet_Users
таблице и скопировать и вставить его в UserId
поле в UserProfiles
. На рисунке 12 показана UserProfiles
таблица после добавления новой записи для Брюса.
Рис. 12. Запись была добавлена UserProfiles
в для Брюса (щелкните, чтобы просмотреть полноразмерное изображение)
Вернитесь на страницу AdditionalUserInfo.aspx
, вошедший в систему под учетной записью Брюса. Как показано на рисунке 13, отображаются параметры Брюса.
Рис. 13. Для текущего посещающего пользователя отображаются его параметры (щелкните для просмотра полноразмерного изображения)
Примечание
Добавьте записи в таблицу UserProfiles
для каждого пользователя членства вручную. На шаге 6 мы рассмотрим, как настроить элемент управления CreateUserWizard для автоматического добавления новой строки в UserProfiles
таблицу при создании новой учетной записи пользователя.
Шаг 3. Разрешение пользователю изменять свой родной город, домашнюю страницу и подпись
На этом этапе вошедший в систему пользователь может просматривать свой родной город, домашнюю страницу и параметры подписи, но пока не может изменить их. Давайте обновим элемент управления DetailsView, чтобы данные можно было редактировать.
Первое, что нам нужно сделать, — это добавить UpdateCommand
для SqlDataSource, указав выполняемую инструкцию UPDATE
и соответствующие параметры. Выберите SqlDataSource и в окне Свойства щелкните многоточие рядом со свойством UpdateQuery, чтобы открыть диалоговое окно Редактор команд и параметров. Введите в текстовое поле следующую UPDATE
инструкцию:
UPDATE UserProfiles SET
HomeTown = @HomeTown,
HomepageUrl = @HomepageUrl,
Signature = @Signature
WHERE UserId = @UserId
Затем нажмите кнопку "Обновить параметры", которая создаст параметр в коллекции элемента управления UpdateParameters
SqlDataSource для каждого из параметров в инструкции UPDATE
. Оставьте источник для всех параметров равным Нет и нажмите кнопку ОК, чтобы завершить диалоговое окно.
Рис. 14. Укажите sqlDataSource UpdateCommand
и UpdateParameters
(щелкните для просмотра полноразмерного изображения)
Из-за добавлений, внесенных в элемент управления SqlDataSource, элемент управления DetailsView теперь может поддерживать редактирование. В смарт-теге DetailsView проверка флажок "Включить редактирование". При этом commandField добавляется в коллекцию элемента управления Fields
со свойством ShowEditButton
True. При этом отрисовывается кнопка Изменить, когда DetailsView отображается в режиме только для чтения, и кнопки Обновить и Отмена при отображении в режиме редактирования. Вместо того, чтобы пользователь нажимал кнопку Изменить, мы можем настроить отрисовку DetailsView в состоянии "всегда редактируемый", задав для свойства элемента управления DefaultMode
DetailsView значение Edit
.
После этих изменений декларативная разметка элемента управления DetailsView должна выглядеть примерно так:
<asp:DetailsView ID="UserProfile" runat="server"
AutoGenerateRows="False" DataKeyNames="UserId"
DataSourceID="UserProfileDataSource" DefaultMode="Edit">
<Fields>
<asp:BoundField DataField="HomeTown" HeaderText="HomeTown"
SortExpression="HomeTown" />
<asp:BoundField DataField="HomepageUrl" HeaderText="HomepageUrl"
SortExpression="HomepageUrl" />
<asp:BoundField DataField="Signature" HeaderText="Signature"
SortExpression="Signature" />
<asp:CommandField ShowEditButton="True" />
</Fields>
</asp:DetailsView>
Обратите внимание на добавление CommandField и DefaultMode
свойства .
Протестируйте эту страницу в браузере. При посещении с пользователем, у которого есть соответствующая запись в UserProfiles
, параметры пользователя отображаются в редактируемом интерфейсе.
Рис. 15. DetailsView отрисовывает редактируемый интерфейс (щелкните, чтобы просмотреть полноразмерное изображение)
Попробуйте изменить значения и нажать кнопку Обновить. Похоже, ничего не происходит. Существует обратная связь, и значения сохраняются в базе данных, но нет визуальной обратной связи о том, что сохранение произошло.
Чтобы устранить эту проблему, вернитесь в Visual Studio и добавьте элемент управления Метка над DetailsView. Задайте для свойства ID
значение SettingsUpdatedMessage
, для свойства Text
— значение "Ваши параметры были обновлены", а для свойств Visible
и EnableViewState
— значение false
.
<asp:Label ID="SettingsUpdatedMessage" runat="server"
Text="Your settings have been updated."
EnableViewState="false"
Visible="false"></asp:Label>
Метка должна отображаться SettingsUpdatedMessage
при каждом обновлении DetailsView. Для этого создайте обработчик событий для события DetailsView ItemUpdated
и добавьте следующий код:
protected void UserProfile_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
{
SettingsUpdatedMessage.Visible = true;
}
Вернитесь на страницу AdditionalUserInfo.aspx
через браузер и обновите данные. На этот раз отображается полезное сообщение о состоянии.
Рис. 16. При обновлении параметров отображается короткое сообщение (щелкните для просмотра полноразмерного изображения)
Примечание
Интерфейс редактирования элемента управления DetailsView оставляет желать лучшего. В нем используются текстовые поля стандартного размера, но поле Подпись, вероятно, должно быть многострочное текстовое поле. Следует использовать RegularExpressionValidator, чтобы URL-адрес домашней страницы, если он был введен, начинался с "http://" или "https://". Кроме того, так как свойство элемента управления DetailsView имеет DefaultMode
значение Edit
, кнопка Отмена ничего не делает. Его следует удалить или перенаправить пользователя на другую страницу (например ~/Default.aspx
, ). Я оставляю эти улучшения как упражнение для читателя.
Добавление ссылки на страницуAdditionalUserInfo.aspx
на главной странице
В настоящее время на веб-сайте нет ссылок на страницу AdditionalUserInfo.aspx
. Единственный способ связаться с ним — ввести URL-адрес страницы непосредственно в адресной строке браузера. Давайте добавим ссылку на эту страницу на Site.master
странице master.
Напомним, что страница master содержит веб-элемент управления LoginView в contentPlaceHolderLoginContent
, который отображает различные разметки для прошедших проверку подлинности и анонимных посетителей. Обновите элемент управления LoggedInTemplate
LoginView, чтобы включить ссылку на страницу AdditionalUserInfo.aspx
. После внесения этих изменений декларативная разметка элемента управления LoginView должна выглядеть примерно так:
<asp:LoginView ID="LoginView1" runat="server">
<LoggedInTemplate>
Welcome back,
<asp:LoginName ID="LoginName1" runat="server" />.
<br />
<asp:HyperLink ID="lnkUpdateSettings" runat="server"
NavigateUrl="~/Membership/AdditionalUserInfo.aspx">
Update Your Settings</asp:HyperLink>
</LoggedInTemplate>
<AnonymousTemplate>
Hello, stranger.
</AnonymousTemplate>
</asp:LoginView>
Обратите внимание на добавление lnkUpdateSettings
элемента управления HyperLink в LoggedInTemplate
. Используя эту ссылку, пользователи, прошедшие проверку подлинности, могут быстро перейти на страницу, чтобы просмотреть и изменить параметры своего родного города, домашней страницы и подписи.
Шаг 4. Добавление новых комментариев гостевой книги
На Guestbook.aspx
этой странице пользователи, прошедшие проверку подлинности, могут просмотреть гостевую книгу и оставить комментарий. Начнем с создания интерфейса для добавления новых комментариев гостевой книги.
Откройте страницу Guestbook.aspx
в Visual Studio и создайте пользовательский интерфейс, состоящий из двух элементов управления TextBox: один для темы нового комментария, а второй — для текста. Задайте для свойства первого элемента управления TextBox значение , а для его Columns
свойства — значение 40, для второго ID
TextMode
MultiLine
Body
— значение , а Width
для свойств и Rows
— значение "95%" и 8 соответственно.Subject
ID
Чтобы завершить работу с пользовательским интерфейсом, добавьте веб-элемент управления Button с именем PostCommentButton
и задайте для его Text
свойства значение "Опубликовать комментарий".
Так как для каждого комментария гостевой книги требуется тема и текст, добавьте RequiredFieldValidator для каждого элемента TextBoxes. Присвойте свойству ValidationGroup
этих элементов управления значение EnterComment; аналогичным образом задайте PostCommentButton
для свойства элемента управления ValidationGroup
значение EnterComment. Дополнительные сведения об ASP. Элементы управления проверки NET, проверка проверку формы в ASP.NET.
После создания пользовательского интерфейса декларативная разметка страницы должна выглядеть примерно так:
<h3>Leave a Comment</h3>
<p>
<b>Subject:</b>
<asp:RequiredFieldValidator ID="SubjectReqValidator" runat="server"
ErrorMessage="You must provide a value for Subject"
ControlToValidate="Subject" ValidationGroup="EnterComment">
</asp:RequiredFieldValidator><br/>
<asp:TextBox ID="Subject" Columns="40" runat="server"></asp:TextBox>
</p>
<p>
<b>Body:</b>
<asp:RequiredFieldValidator ID="BodyReqValidator" runat="server"
ControlToValidate="Body"
ErrorMessage="You must provide a value for Body" ValidationGroup="EnterComment">
</asp:RequiredFieldValidator><br/>
<asp:TextBox ID="Body" TextMode="MultiLine" Width="95%"
Rows="8" runat="server"></asp:TextBox>
</p>
<p>
<asp:Button ID="PostCommentButton" runat="server"
Text="Post Your Comment"
ValidationGroup="EnterComment" />
</p>
После завершения пользовательского интерфейса наша следующая задача — вставить новую запись в таблицу GuestbookComments
при щелчке PostCommentButton
. Это можно сделать несколькими способами: мы можем написать ADO.NET код в обработчике событий Button Click
; добавить элемент управления SqlDataSource на страницу, настроить его InsertCommand
, а затем вызвать его Insert
метод из Click
обработчика событий; или создать средний уровень, отвечающий за вставку новых комментариев гостевой книги, и вызвать эту функцию из Click
обработчика событий. Так как мы рассмотрели использование SqlDataSource на шаге 3, давайте используем ADO.NET код здесь.
Примечание
Классы ADO.NET, используемые для программного доступа к данным из базы данных Microsoft SQL Server, находятся в System.Data.SqlClient
пространстве имен . Может потребоваться импортировать это пространство имен в класс кода программной части страницы (т. е. using System.Data.SqlClient;
).
Создайте обработчик событий для PostCommentButton
Click
события и добавьте следующий код:
protected void PostCommentButton_Click(object sender, EventArgs e)
{
if (!Page.IsValid)
return;
// Determine the currently logged on user's UserId
MembershipUser currentUser = Membership.GetUser();
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
// Insert a new record into GuestbookComments
string connectionString =
ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
string insertSql = "INSERT INTO GuestbookComments(Subject, Body, UserId) VALUES(@Subject,
@Body, @UserId)";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = new SqlCommand(insertSql, myConnection);
myCommand.Parameters.AddWithValue("@Subject", Subject.Text.Trim());
myCommand.Parameters.AddWithValue("@Body", Body.Text.Trim());
myCommand.Parameters.AddWithValue("@UserId", currentUserId);
myCommand.ExecuteNonQuery();
myConnection.Close();
}
// "Reset" the Subject and Body TextBoxes
Subject.Text = string.Empty;
Body.Text = string.Empty;
}
Обработчик Click
событий начинается с проверки допустимости предоставленных пользователем данных. Если это не так, обработчик событий завершает работу перед вставкой записи. При условии, что предоставленные данные являются допустимыми, текущее значение пользователя UserId
, вошедшего в систему, извлекается и сохраняется в локальной переменной currentUserId
. Это значение необходимо, так как необходимо указать UserId
значение при вставке записи в GuestbookComments
.
После этого строка подключения для SecurityTutorials
базы данных извлекается из Web.config
и INSERT
указывается инструкция SQL. SqlConnection
Затем создается и открывается объект . SqlCommand
Затем создается объект и назначаются значения для параметров, используемых в запросеINSERT
. Затем INSERT
выполняется инструкция и соединение закрывается. В конце обработчика событий свойства и Body
TextBoxes Text
очищаются, Subject
чтобы значения пользователя не сохранялись во время обратной передачи.
Протестируйте эту страницу в браузере. Так как эта страница находится в папке Membership
, она недоступна анонимным посетителям. Поэтому необходимо сначала войти в систему (если это еще не сделано). Введите значение в Subject
и Body
TextBoxes и нажмите кнопку PostCommentButton
. Это приведет к добавлению новой записи в GuestbookComments
. При обратной отправке указанные тема и текст удаляются из textBoxes.
После нажатия кнопки PostCommentButton
визуальный отзыв о добавлении комментария в гостевую книгу отсутствует. Нам по-прежнему нужно обновить эту страницу для отображения существующих комментариев гостевой книги, что мы сделаем на шаге 5. После этого только что добавленный комментарий появится в списке комментариев, обеспечивая адекватную визуальную обратную связь. На данный момент убедитесь, что комментарий гостевой книги сохранен, изучив содержимое GuestbookComments
таблицы.
На рисунке 17 показано содержимое GuestbookComments
таблицы после того, как остались два комментария.
Рис. 17. Вы можете просмотреть примечания гостевой книги GuestbookComments
в таблице (щелкните, чтобы просмотреть полноразмерное изображение)
Примечание
Если пользователь пытается вставить комментарий гостевой книги, содержащий потенциально опасную разметку, например HTML, ASP.NET вызовет HttpRequestValidationException
исключение . Дополнительные сведения об этом исключении, причинах его возникновения и о том, как разрешить пользователям отправлять потенциально опасные значения, см. в техническом документе По запросу проверки.
Шаг 5. Перечисление существующих комментариев гостевой книги
Помимо примечаний, пользователь, посещающий страницу Guestbook.aspx
, также должен иметь возможность просматривать существующие комментарии гостевой книги. Для этого добавьте элемент управления ListView с именем CommentList
в нижнюю часть страницы.
Примечание
Элемент управления ListView является новым для ASP.NET версии 3.5. Он предназначен для отображения списка элементов в очень настраиваемом и гибком макете, но по-прежнему предлагает встроенные функции редактирования, вставки, удаления, разбиения по страницам и сортировки, такие как GridView. Если вы используете ASP.NET 2.0, вам потребуется использовать элемент управления DataList или Repeater. Дополнительные сведения об использовании ListView см. в записи блога Скотта Гатри, Элемент управления asp:ListView и моей статье Отображение данных с помощью элемента управления ListView.
Откройте смарт-тег ListView и в раскрывающемся списке Выбор источника данных привяжите элемент управления к новому источнику данных. Как мы видели на шаге 2, запустится мастер настройки источника данных. Щелкните значок База данных, присвойте результирующее имя SqlDataSource CommentsDataSource
и нажмите кнопку ОК. Затем выберите SecurityTutorialsConnectionString
строку подключения из раскрывающегося списка и нажмите кнопку Далее.
На этом этапе на шаге 2 мы указали данные для запроса, выбрав таблицу UserProfiles
из раскрывающегося списка и выбрав возвращаемые столбцы (см. рис. 9). Однако на этот раз мы хотим создать инструкцию SQL, которая извлекает не только записи из GuestbookComments
, но и родной город, домашнюю страницу, подпись и имя пользователя комментатора. Поэтому установите переключатель "Указать пользовательскую инструкцию SQL или хранимую процедуру" и нажмите кнопку Далее.
Откроется экран "Определение пользовательских инструкций или хранимых процедур". Нажмите кнопку Построитель запросов, чтобы выполнить графическую сборку запроса. Построитель запросов начинается с запроса на указание таблиц, из которого требуется выполнить запрос. GuestbookComments
Выберите таблицы , UserProfiles
и aspnet_Users
и нажмите кнопку ОК. Это приведет к добавлению всех трех таблиц в область конструктора. Так как в GuestbookComments
таблицах , UserProfiles
и aspnet_Users
существуют ограничения внешнего ключа, построитель запросов автоматически создает JOIN
эти таблицы.
Остается только указать возвращаемые столбцы. GuestbookComments
В таблице выберите Subject
столбцы , Body
и CommentDate
; возвращает HomeTown
столбцы , HomepageUrl
и Signature
из UserProfiles
таблицы; возвращается UserName
из aspnet_Users
. Кроме того, добавьте "ORDER BY CommentDate DESC
" в конец SELECT
запроса, чтобы в первую очередь возвращались самые последние записи. После выбора этих элементов интерфейс построителя запросов должен выглядеть примерно так, как на снимке экрана на рис. 18.
Рис. 18. Созданный запрос JOIN
GuestbookComments
с таблицами , UserProfiles
и aspnet_Users
(щелкните для просмотра полноразмерного изображения)
Нажмите кнопку ОК, чтобы закрыть окно построителя запросов и вернуться к экрану "Определение пользовательских инструкций или хранимых процедур". Нажмите кнопку Далее, чтобы перейти к экрану "Тестовый запрос", где можно просмотреть результаты запроса, нажав кнопку Тестировать запрос. Когда все будет готово, нажмите кнопку Готово, чтобы завершить работу мастера настройки источника данных.
Когда мы завершили работу мастера настройки источника данных на шаге 2, коллекция связанного элемента управления DetailsView была обновлена Fields
, чтобы включить BoundField для каждого столбца, возвращаемого SelectCommand
объектом . ListView, однако, остается без изменений; Нам по-прежнему нужно определить его макет. Макет ListView можно создать вручную с помощью декларативной разметки или из параметра "Настроить ListView" в смарт-теге. Я обычно предпочитаю определять разметку вручную, но использовать любой метод является наиболее естественным для вас.
В итоге я использовал следующие LayoutTemplate
, ItemTemplate
и ItemSeparatorTemplate
для элемента управления ListView:
<asp:ListView ID="CommentList" runat="server" DataSourceID="CommentsDataSource">
<LayoutTemplate>
<span ID="itemPlaceholder" runat="server" />
<p>
<asp:DataPager ID="DataPager1" runat="server">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button"
ShowFirstPageButton="True"
ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</p>
</LayoutTemplate>
<ItemTemplate>
<h4><asp:Label ID="SubjectLabel" runat="server"
Text='<%# Eval("Subject") %>' /></h4>
<asp:Label ID="BodyLabel" runat="server"
Text='<%# Eval("Body").ToString().Replace(Environment.NewLine, "<br />") %>' />
<p>
---<br />
<asp:Label ID="SignatureLabel" Font-Italic="true" runat="server"
Text='<%# Eval("Signature") %>' />
<br />
<br />
My Home Town:
<asp:Label ID="HomeTownLabel" runat="server"
Text='<%# Eval("HomeTown") %>' />
<br />
My Homepage:
<asp:HyperLink ID="HomepageUrlLink" runat="server"
NavigateUrl='<%# Eval("HomepageUrl") %>'
Text='<%# Eval("HomepageUrl") %>' />
</p>
<p align="center">
Posted by
<asp:Label ID="UserNameLabel" runat="server"
Text='<%# Eval("UserName") %>' /> on
<asp:Label ID="CommentDateLabel" runat="server"
Text='<%# Eval("CommentDate") %>' />
</p>
</ItemTemplate>
<ItemSeparatorTemplate>
<hr />
</ItemSeparatorTemplate>
</asp:ListView>
LayoutTemplate
определяет разметку, выдаваемую элементом управления , в то время как ItemTemplate
отрисовывает каждый элемент, возвращаемый sqlDataSource. Результирующая ItemTemplate
разметка помещается в LayoutTemplate
itemPlaceholder
элемент управления . Помимо itemPlaceholder
, LayoutTemplate
включает элемент управления DataPager, который ограничивает ListView отображением только 10 комментариев гостевой книги на страницу (по умолчанию) и отображает интерфейс подкачки.
My ItemTemplate
отображает тему каждого комментария гостевой книги в элементе с текстом <h4>
, расположенным под темой. Обратите внимание, что синтаксис, используемый для отображения текста, принимает данные, возвращаемые оператором Eval("Body")
привязки данных, преобразует их в строку и заменяет разрывы строк элементом <br />
. Это преобразование необходимо для отображения разрывов строк, введенных при отправке комментария, так как пробелы игнорируются HTML. Подпись пользователя отображается под текстом курсивом, за которым следует родной город пользователя, ссылка на его домашнюю страницу, дата и время создания комментария, а также имя пользователя, оставившего комментарий.
Просмотрите страницу в браузере. Здесь должны отобразиться комментарии, добавленные в гостевую книгу на шаге 5.
Рис. 19. Guestbook.aspx
Теперь отображаются комментарии гостевой книги (щелкните для просмотра полноразмерного изображения)
Попробуйте добавить новый комментарий в гостевую книгу. После нажатия кнопки PostCommentButton
страница публикуется обратно, и комментарий добавляется в базу данных, но элемент управления ListView не обновляется для отображения нового комментария. Это можно исправить с помощью следующих способов:
PostCommentButton
Обновление обработчика событий кнопкиClick
таким образом, чтобы он вызвал метод элемента управленияDataBind()
ListView после вставки нового комментария в базу данных;- Присвойтите
EnableViewState
свойству элемента управления ListView значениеfalse
. Этот подход работает потому, что, отключив состояние представления элемента управления, он должен повторно привязывать к базовым данным при каждой обратной отправке.
На веб-сайте руководства, который можно скачать из этого руководства, иллюстрируются оба метода. Свойство элемента управления EnableViewState
ListView и false
код, необходимый для программной повторной привязки данных к ListView, присутствует в обработчике Click
событий, но закомментирован.
Примечание
В настоящее AdditionalUserInfo.aspx
время страница позволяет пользователю просматривать и изменять параметры своего родного города, домашней страницы и подписи. Было бы неплохо обновить AdditionalUserInfo.aspx
, чтобы отобразить комментарии вошедшего пользователя в гостевую книгу. То есть, помимо изучения и изменения информации, пользователь может посетить страницу AdditionalUserInfo.aspx
, чтобы увидеть, какие комментарии гостевой книги он сделал в прошлом. Я оставляю это как упражнение для заинтересованного читателя.
Шаг 6. Настройка элемента управления CreateUserWizard для включения интерфейса для домашнего города, домашней страницы и подписи
Запрос SELECT
, используемый страницей Guestbook.aspx
INNER JOIN
, использует для объединения связанных записей между GuestbookComments
таблицами , UserProfiles
и aspnet_Users
. Если пользователь, у которого нет записи в UserProfiles
, делает комментарий гостевой книги, комментарий не будет отображаться в ListView, так как INNER JOIN
возвращает GuestbookComments
записи только при наличии совпадающих записей в UserProfiles
и aspnet_Users
. И, как мы видели на шаге 3, если у пользователя нет записи, UserProfiles
он не сможет просматривать или изменять свои параметры на AdditionalUserInfo.aspx
странице.
Излишне говорить, что из-за наших проектных решений важно, чтобы каждая учетная запись пользователя в системе членства была соответствующая запись в UserProfiles
таблице. Нам нужно, чтобы соответствующая запись добавлялась UserProfiles
в каждый раз, когда создается новая учетная запись участника с помощью CreateUserWizard.
Как описано в руководстве По созданию учетных записей пользователей, после создания новой учетной записи участника элемент управления CreateUserWizard вызывает событиеCreatedUser
. Мы можем создать обработчик событий для этого события, получить Идентификатор пользователя для только что созданного пользователя, а затем вставить запись в таблицу UserProfiles
со значениями по умолчанию для HomeTown
столбцов , HomepageUrl
и Signature
. Более того, можно заставить у пользователя эти значения, настроив интерфейс элемента управления CreateUserWizard для включения дополнительных элементов TextBoxes.
Давайте сначала рассмотрим, как добавить новую строку в таблицу UserProfiles
в обработчике CreatedUser
событий со значениями по умолчанию. После этого мы посмотрим, как настроить пользовательский интерфейс элемента управления CreateUserWizard, чтобы включить дополнительные поля формы для сбора сведений о родном городе, домашней странице и подписи нового пользователя.
Добавление строки по умолчанию вUserProfiles
В учебнике Создание учетных записей пользователей мы добавили элемент управления CreateUserWizard на страницу CreatingUserAccounts.aspx
в папке Membership
. Чтобы элемент управления CreateUserWizard добавлял запись в таблицу UserProfiles
при создании учетной записи пользователя, необходимо обновить функциональные возможности элемента управления CreateUserWizard. Вместо того, чтобы вносить эти изменения на страницу CreatingUserAccounts.aspx
, давайте добавим новый элемент управления CreateUserWizard на страницу EnhancedCreateUserWizard.aspx
и внесите изменения для этого руководства.
Откройте страницу EnhancedCreateUserWizard.aspx
в Visual Studio и перетащите элемент управления CreateUserWizard с панели элементов на страницу. Задайте для свойства элемента управления ID
CreateUserWizard значение NewUserWizard
. Как мы говорили в руководстве По созданию учетных записей пользователей , пользовательский интерфейс CreateUserWizard по умолчанию запрашивает у посетителя необходимые сведения. После того как эта информация будет предоставлена, элемент управления внутренне создает новую учетную запись пользователя на платформе членства, при этом нам не нужно писать ни одной строки кода.
Элемент управления CreateUserWizard вызывает ряд событий во время рабочего процесса. После того как посетитель отправит сведения о запросе и отправит форму, элемент управления CreateUserWizard изначально запускает своеCreatingUser
событие. Если во время создания возникла проблема, CreateUserError
событие запускается; однако в случае успешного создания CreatedUser
пользователя возникает событие . В учебнике Создание учетных записей пользователей мы создали обработчик событий для CreatingUser
события, чтобы убедиться, что указанное имя пользователя не содержит начальных или конечных пробелов, а имя пользователя не отображается в пароле.
Чтобы добавить строку в таблицу UserProfiles
для только что созданного пользователя, необходимо создать обработчик CreatedUser
события. К моменту CreatedUser
возникновения события учетная запись пользователя уже была создана на платформе членства, что позволяет нам получить значение UserId учетной записи.
Создайте обработчик событий для NewUserWizard
CreatedUser
события и добавьте следующий код:
protected void NewUserWizard_CreatedUser(object sender, EventArgs e)
{
// Get the UserId of the just-added user
MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
Guid newUserId = (Guid)newUser.ProviderUserKey;
// Insert a new record into UserProfiles
string connectionString =
ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
string insertSql = "INSERT INTO UserProfiles(UserId, HomeTown, HomepageUrl,
Signature) VALUES(@UserId, @HomeTown, @HomepageUrl, @Signature)";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = new SqlCommand(insertSql, myConnection);
myCommand.Parameters.AddWithValue("@UserId", newUserId);
myCommand.Parameters.AddWithValue("@HomeTown", DBNull.Value);
myCommand.Parameters.AddWithValue("@HomepageUrl", DBNull.Value);
myCommand.Parameters.AddWithValue("@Signature", DBNull.Value);
myCommand.ExecuteNonQuery();
myConnection.Close();
}
}
Приведенный выше код создается путем получения Идентификатора пользователя только что добавленной учетной записи пользователя. Это достигается с помощью Membership.GetUser(username)
метода для возврата сведений о конкретном пользователе, а затем с помощью ProviderUserKey
свойства для получения идентификатора пользователя. Имя пользователя, введенное пользователем в элементе управления CreateUserWizard, доступно через его UserName
свойство .
Затем строка подключения извлекается из Web.config
и INSERT
указывается оператор . Создаются необходимые ADO.NET объекты и выполняется команда . Код назначает DBNull
экземпляр параметрам , @HomepageUrl
и @Signature
, что приводит к @HomeTown
вставке значений базы данных NULL
для HomeTown
полей , HomepageUrl
и Signature
.
Перейдите на страницу EnhancedCreateUserWizard.aspx
в браузере и создайте новую учетную запись пользователя. После этого вернитесь в Visual Studio и изучите содержимое aspnet_Users
таблиц и UserProfiles
(как это было на рис. 12). Вы увидите новую учетную запись пользователя в aspnet_Users
и соответствующую UserProfiles
строку (со значениями NULL
HomeTown
, HomepageUrl
и Signature
).
Рис. 20. Добавлена новая учетная запись пользователя и UserProfiles
запись (щелкните для просмотра полноразмерного изображения)
После того как посетитель предоставил сведения о своей новой учетной записи и нажал кнопку "Создать пользователя", создается учетная запись пользователя и в таблицу UserProfiles
добавляется строка. Затем в createUserWizard отображается , CompleteWizardStep
в котором отображается сообщение об успешном выполнении и кнопка Продолжить. Нажатие кнопки Продолжить приводит к обратной отправке, но никаких действий не выполняется, в результате чего пользователь зависает на EnhancedCreateUserWizard.aspx
странице.
Можно указать URL-адрес для отправки пользователю при нажатии кнопки Продолжить с помощью свойства элемента управления ContinueDestinationPageUrl
CreateUserWizard. Задайте для ContinueDestinationPageUrl
свойства значение "~/Membership/AdditionalUserInfo.aspx". При этом новый пользователь перейдет в AdditionalUserInfo.aspx
, где он может просматривать и обновлять свои параметры.
Настройка интерфейса CreateUserWizard для запроса домашнего города, домашней страницы и подписи нового пользователя
Интерфейса по умолчанию элемента управления CreateUserWizard достаточно для простых сценариев создания учетных записей, в которых необходимо собирать только основные сведения об учетной записи пользователя, такие как имя пользователя, пароль и электронная почта. Но что делать, если мы хотим предложить посетителю войти в ее родной город, домашнюю страницу, и подпись при создании ее учетной записи? Интерфейс элемента управления CreateUserWizard можно настроить для сбора дополнительных сведений при регистрации. Эти сведения можно использовать в CreatedUser
обработчике событий для вставки дополнительных записей в базовую базу данных.
Элемент управления CreateUserWizard расширяет элемент управления мастер ASP.NET, который является элементом управления, который позволяет разработчику страниц определить ряд упорядоченных WizardSteps
. Элемент управления "Мастер" отображает активный шаг и предоставляет интерфейс навигации, позволяющий посетителю пройти эти шаги. Элемент управления "Мастер" идеально подходит для разбиения длинной задачи на несколько коротких шагов. Дополнительные сведения об элементе управления "Мастер" см. в разделе Создание пошагового пользовательского интерфейса с помощью элемента управления мастера ASP.NET 2.0.
Разметка элемента управления CreateUserWizard по умолчанию определяет два WizardSteps
: CreateUserWizardStep
и 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
отображает интерфейс, который запрашивает имя пользователя, пароль, адрес электронной почты и т. д. Когда посетитель предоставляет эти сведения и нажимает кнопку "Создать пользователя", ей отображается CompleteWizardStep
сообщение об успешном выполнении и кнопка Продолжить.
Чтобы настроить интерфейс элемента управления CreateUserWizard для включения дополнительных полей формы, можно:
Создание одного или нескольких новых
WizardStep
, чтобы содержать дополнительные элементы пользовательского интерфейса. Чтобы добавить новыйWizardStep
объект в CreateUserWizard, щелкните ссылку "Добавить/удалитьWizardSteps
" в смарт-теге, чтобы запустить редактор коллекцийWizardStep
. Оттуда можно добавить, удалить или изменить порядок действий в мастере. Это подход, который мы будем использовать в этом руководстве.CreateUserWizardStep
Преобразованиев редактируемый объектWizardStep
. Это заменяет наCreateUserWizardStep
эквивалентWizardStep
, разметка которого определяет пользовательский интерфейс, соответствующийCreateUserWizardStep
. Преобразовав вCreateUserWizardStep
,WizardStep
можно изменить положение элементов управления или добавить дополнительные элементы пользовательского интерфейса на этом шаге. Чтобы преобразоватьCreateUserWizardStep
илиCompleteWizardStep
в редактируемыйWizardStep
, щелкните ссылку "Настроить шаг создания пользователя" или "Настроить полный шаг" в смарт-теге элемента управления.Используйте некоторое сочетание указанных выше двух вариантов.
Важно помнить, что элемент управления CreateUserWizard выполняет процесс создания учетной записи пользователя при нажатии кнопки "Создать пользователя" в его CreateUserWizardStep
. Не имеет значения, есть ли дополнительные WizardStep
после CreateUserWizardStep
или нет.
При добавлении пользовательского в WizardStep
элемент управления CreateUserWizard для сбора дополнительных пользовательских данных WizardStep
пользователь может быть размещен до или после CreateUserWizardStep
. Если он поставляется до CreateUserWizardStep
, то для обработчика событий доступны дополнительные входные данные, собранные пользователем из пользовательского WizardStep
CreatedUser
объекта . Однако если пользователь WizardStep
возникает после CreateUserWizardStep
, то к тому времени, когда WizardStep
пользователь отображается, новая учетная запись пользователя уже создана и CreatedUser
событие уже сработало.
На рисунке 21 показан рабочий процесс, когда добавленный WizardStep
предшествует CreateUserWizardStep
. Так как к моменту CreatedUser
возникновения события были собраны дополнительные сведения о пользователе, достаточно обновить CreatedUser
обработчик событий, чтобы получить эти входные данные и использовать их для INSERT
значений параметров инструкции (а не DBNull.Value
).
Рис. 21. Рабочий процесс CreateUserWizard, когда перед элементом Additional WizardStep
предшествует CreateUserWizardStep
(щелкните для просмотра полноразмерного изображения)
Если пользователь WizardStep
размещается послеCreateUserWizardStep
, процесс создания учетной записи пользователя происходит до того, как пользователь может войти в свой родной город, домашнюю страницу или подпись. В этом случае эти дополнительные сведения необходимо вставить в базу данных после создания учетной записи пользователя, как показано на рисунке 22.
Рис. 22. Рабочий процесс CreateUserWizard При дополнительном WizardStep
наступает после CreateUserWizardStep
(щелкните для просмотра полноразмерного изображения)
Рабочий процесс, показанный на рис. 22, ожидает вставки записи в таблицу UserProfiles
до завершения шага 2. Однако если посетитель закроет браузер после шага 1, мы достигли состояния, в котором была создана учетная запись пользователя, но запись не была добавлена в UserProfiles
. Одним из обходных решений является вставка UserProfiles
записи со значениями NULL
или по умолчанию в CreatedUser
обработчик событий (которая возникает после шага 1), а затем обновление этой записи после завершения шага 2. Это гарантирует, что UserProfiles
запись будет добавлена для учетной записи пользователя, даже если пользователь завершит процесс регистрации в середине.
В этом руководстве давайте создадим новый WizardStep
объект, который возникает после , CreateUserWizardStep
но перед CompleteWizardStep
. Давайте сначала настроим МастерШаг, а затем рассмотрим код.
В смарт-теге элемента управления CreateUserWizard выберите "Добавить/удалить WizardStep
", чтобы открыть диалоговое окно Редактор коллекций WizardStep
. Добавьте новый WizardStep
объект , задав для нее ID
значение UserSettings
, а для Title
параметра — значение "Ваши параметры" и значение StepType
Step
. Затем разместите его так, чтобы он располагал после CreateUserWizardStep
("Регистрация для новой учетной записи") и перед CompleteWizardStep
("Завершить"), как показано на рис. 23.
Рис. 23. Добавление нового WizardStep
элемента управления CreateUserWizard (щелкните для просмотра полноразмерного изображения)
Нажмите кнопку ОК, чтобы закрыть диалоговое WizardStep
окно Редактор коллекции. О новом WizardStep
свидетельствует обновленная декларативная разметка элемента управления CreateUserWizard:
<asp:CreateUserWizard ID="NewUserWizard" runat="server"
ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:WizardStep runat="server" ID="UserSettings" StepType="Step"
Title="Your Settings">
</asp:WizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
Обратите внимание на новый <asp:WizardStep>
элемент . Нам нужно добавить пользовательский интерфейс для сбора родного города, домашней страницы и подписи нового пользователя здесь. Это содержимое можно ввести в декларативном синтаксисе или с помощью Designer. Чтобы использовать Designer, выберите шаг "Параметры" в раскрывающемся списке смарт-тега, чтобы просмотреть этот шаг в Designer.
Примечание
При выборе шага в раскрывающемся списке Смарт-тега обновляется свойство элемента управления ActiveStepIndex
CreateUserWizard, указывающее индекс начального шага. Поэтому если вы используете этот раскрывающийся список для изменения шага "Ваши параметры" в Designer, обязательно установите для него значение "Регистрация для новой учетной записи", чтобы этот шаг отображалось при первом посещении EnhancedCreateUserWizard.aspx
страницы пользователями.
Создайте пользовательский интерфейс на шаге "Параметры", который содержит три элемента управления TextBox с именами HomeTown
, HomepageUrl
и Signature
. После создания этого интерфейса декларативная разметка CreateUserWizard должна выглядеть примерно так:
<asp:CreateUserWizard ID="NewUserWizard" runat="server"
ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:WizardStep runat="server" ID="UserSettings" StepType="Step"
Title="Your Settings">
<p>
<b>Home Town:</b><br />
<asp:TextBox ID="HomeTown" runat="server"></asp:TextBox>
</p>
<p>
<b>Homepage URL:</b><br />
<asp:TextBox ID="HomepageUrl" Columns="40" runat="server"></asp:TextBox>
</p>
<p>
<b>Signature:</b><br />
<asp:TextBox ID="Signature" TextMode="MultiLine" Width="95%"
Rows="5" runat="server"></asp:TextBox>
</p>
</asp:WizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
Перейдите на эту страницу в браузере и создайте учетную запись пользователя, указав значения для родного города, домашней страницы и подписи. После завершения CreateUserWizardStep
действия учетная запись пользователя создается на платформе членства и CreatedUser
запускается обработчик событий, который добавляет новую строку в UserProfiles
, но со значением HomeTown
базы данных NULL
, HomepageUrl
и Signature
. Значения, введенные для родного города, домашней страницы и подписи, никогда не используются. Конечным результатом является новая учетная запись пользователя с записью UserProfiles
, поля которой HomeTown
, HomepageUrl
и Signature
еще не указаны.
Нам нужно выполнить код после шага "Параметры", который принимает значения родного города, honepage и сигнатуры, введенные пользователем, и обновляет соответствующую UserProfiles
запись. Каждый раз, когда пользователь перемещается между шагами в элементе управления "Мастер"ActiveStepChanged
, возникает событие мастера. Мы можем создать обработчик событий для этого события и обновить таблицу UserProfiles
после завершения шага "Параметры".
Добавьте обработчик событий для события CreateUserWizard ActiveStepChanged
и добавьте следующий код:
protected void NewUserWizard_ActiveStepChanged(object sender, EventArgs e)
{
// Have we JUST reached the Complete step?
if (NewUserWizard.ActiveStep.Title == "Complete")
{
WizardStep UserSettings = NewUserWizard.FindControl("UserSettings") as
WizardStep;
// Programmatically reference the TextBox controls
TextBox HomeTown = UserSettings.FindControl("HomeTown") as TextBox;
TextBox HomepageUrl = UserSettings.FindControl("HomepageUrl") as TextBox;
TextBox Signature = UserSettings.FindControl("Signature") as TextBox;
// Update the UserProfiles record for this user
// Get the UserId of the just-added user
MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
Guid newUserId = (Guid)newUser.ProviderUserKey;
// Insert a new record into UserProfiles
string connectionString =
ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
string updateSql = "UPDATE UserProfiles SET HomeTown = @HomeTown, HomepageUrl
= @HomepageUrl, Signature = @Signature WHERE UserId = @UserId";
using (SqlConnection myConnection = new SqlConnection(connectionString))
{
myConnection.Open();
SqlCommand myCommand = new SqlCommand(updateSql, myConnection);
myCommand.Parameters.AddWithValue("@HomeTown", HomeTown.Text.Trim());
myCommand.Parameters.AddWithValue("@HomepageUrl", HomepageUrl.Text.Trim());
myCommand.Parameters.AddWithValue("@Signature", Signature.Text.Trim());
myCommand.Parameters.AddWithValue("@UserId", newUserId);
myCommand.ExecuteNonQuery();
myConnection.Close();
}
}
}
Приведенный выше код начинается с определения того, достигли ли мы только что шага "Завершить". Так как шаг "Завершить" происходит сразу после шага "Ваши параметры", то, когда посетитель достигает шага "Завершить", это означает, что он только что завершил шаг "Ваши параметры".
В этом случае необходимо программно ссылаться на элементы управления TextBox в UserSettings WizardStep
. Для этого сначала используется FindControl
метод для программной ссылки на UserSettings WizardStep
, а затем снова для ссылки на TextBoxes из WizardStep
. После того как на TextBoxes будет указана ссылка, мы готовы выполнить инструкцию UPDATE
. Оператор UPDATE
имеет то же количество параметров, что INSERT
и оператор в CreatedUser
обработчике событий, но здесь мы используем значения родной город, домашняя страница и подпись, предоставленные пользователем.
С помощью этого обработчика событий перейдите на страницу EnhancedCreateUserWizard.aspx
в браузере и создайте учетную запись пользователя, указав значения для родного города, домашней страницы и подписи. После создания новой учетной записи вы будете перенаправлены на AdditionalUserInfo.aspx
страницу, где отображаются только что введенные сведения о родном городе, домашней странице и подписи.
Примечание
Сейчас на нашем веб-сайте есть две страницы, на которых посетитель может создать новую учетную запись: CreatingUserAccounts.aspx
и EnhancedCreateUserWizard.aspx
. Карта сайта и страница входа на веб-сайте указывают на CreatingUserAccounts.aspx
страницу, но CreatingUserAccounts.aspx
страница не запрашивает у пользователя сведения о родном городе, домашней странице и подписи и не добавляет соответствующую строку в UserProfiles
. Поэтому либо обновите страницу CreatingUserAccounts.aspx
, чтобы она предлагала эту функцию, либо обновите карту сайта и страницу входа на ссылку EnhancedCreateUserWizard.aspx
вместо CreatingUserAccounts.aspx
. Если вы выбрали последний вариант, обязательно обновите Membership
файл папки Web.config
, чтобы разрешить анонимным пользователям доступ к EnhancedCreateUserWizard.aspx
странице.
Сводка
В этом руководстве мы рассмотрели методы моделирования данных, связанных с учетными записями пользователей на платформе членства. В частности, мы рассмотрели моделирование сущностей, которые совместно используют связь "один ко многим" с учетными записями пользователей, а также данные, которые имеют отношение "один к одному". Кроме того, мы узнали, как эти связанные сведения могут отображаться, вставляться и обновляться, в некоторых примерах используется элемент управления SqlDataSource, а другие — с помощью ADO.NET кода.
В этом руководстве мы завершаем работу с учетными записями пользователей. Начиная со следующего руководства мы рассмотрим роли. В следующих руководствах мы рассмотрим платформу ролей, узнаем, как создавать новые роли, как назначать роли пользователям, как определить, к каким ролям принадлежит пользователь, и как применить авторизацию на основе ролей.
Счастливое программирование!
Дополнительные материалы
Дополнительные сведения по темам, рассматриваемым в этом руководстве, см. в следующих ресурсах:
- Доступ к данным и их обновление в ASP.NET 2.0
- Элемент управления мастера ASP.NET 2.0
- Создание пошагового пользовательского интерфейса с помощью элемента управления мастера ASP.NET 2.0
- Создание пользовательских параметров элемента управления DataSource
- Настройка элемента управления CreateUserWizard
- СведенияПросмотр кратких руководств по элементам управления
- Отображение данных с помощью элемента управления ListView
- Разбор элементов управления проверкой в ASP.NET 2.0
- Изменение вставки и удаления данных
- Проверка формы в ASP.NET
- Сбор пользовательских сведений о регистрации пользователей
- Профили в ASP.NET 2.0
- Элемент управления asp:ListView
- Краткое руководство по профилям пользователей
Об авторе
Скотт Митчелл (Scott Mitchell), автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Скотт можно связаться по адресу mitchell@4guysfromrolla.com или через его блог по адресу http://ScottOnWriting.NET.
Отдельная благодарность...
Эта серия учебников была проверена многими полезными рецензентами. Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, опустите мне строку в mitchell@4GuysFromRolla.com.