Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Замечание
С тех пор как эта статья была написана, поставщики членства ASP.NET были заменены ASP.NET Identity. Настоятельно рекомендуется обновлять приложения для использования платформы ASP.NET Identity, а не поставщиков членства ASP.NET, которые были представлены на момент написания этой статьи. ASP.NET Identity имеет ряд преимуществ по сравнению с системой членства ASP.NET, в том числе:
- Улучшенная производительность
- Улучшенная расширяемость и возможность тестирования
- Поддержка OAuth, OpenID Connect и двухфакторной проверки подлинности
- Поддержка индентификации на основе утверждений
- Улучшение взаимодействия с ASP.Net Core
Скачивание кода или скачивание PDF
В этом руководстве мы создадим две страницы ASP.NET для управления пользователями, принадлежащими к каким ролям. Первая страница будет включать средства, чтобы узнать, к каким пользователям принадлежит определенная роль, к каким ролям принадлежит конкретный пользователь, а также возможность назначать или удалять конкретного пользователя из определенной роли. На второй странице мы добавим элемент управления CreateUserWizard, чтобы он включает шаг, чтобы указать, к каким ролям принадлежит только что созданный пользователь. Это полезно в сценариях, когда администратор может создавать новые учетные записи пользователей.
Введение
В предыдущем руководстве рассматривался фреймворк ролей и, как использовать класс Roles для создания, извлечения и удаления ролей. Помимо создания и удаления ролей, необходимо иметь возможность назначать или удалять пользователей из роли. К сожалению, ASP.NET не предоставляет никаких веб-элементов управления для управления тем, к каким ролям принадлежат пользователи. Вместо этого необходимо создать собственные ASP.NET страницы для управления этими связями. Хорошая новость заключается в том, что добавлять и удалять пользователей в роли довольно легко. Класс Roles содержит ряд методов для добавления одного или нескольких пользователей в одну или несколько ролей.
В этом руководстве мы создадим две страницы ASP.NET для управления пользователями, принадлежащими к каким ролям. Первая страница будет включать средства, чтобы узнать, к каким пользователям принадлежит определенная роль, к каким ролям принадлежит конкретный пользователь, а также возможность назначать или удалять конкретного пользователя из определенной роли. На второй странице мы добавим элемент управления CreateUserWizard, чтобы он включает шаг, чтобы указать, к каким ролям принадлежит только что созданный пользователь. Это полезно в сценариях, когда администратор может создавать новые учетные записи пользователей.
Давайте приступим!
Перечисление того, какие пользователи относятся к каким ролям
Первое, что нужно сделать в этом руководстве, — это создать веб-страницу, на которой пользователи могут быть назначены на роли. Прежде чем мы заботимся о том, как назначать пользователей ролям, давайте сначала сосредоточимся на том, как определить, какие пользователи относятся к каким ролям. Эти сведения можно отобразить двумя способами: "по роли" или "по пользователю". Мы могли бы разрешить посетителю выбрать роль, а затем показать им всех пользователей, принадлежащих этой роли (отображение "по роли"), или мы могли бы предложить посетителю выбрать пользователя, а затем показать им роли, назначенные данному пользователю (отображение "по пользователю").
Представление "по роли" полезно в случаях, когда посетитель хочет знать набор пользователей, принадлежащих определенной роли; Представление "по пользователю" идеально подходит, когда посетитель должен знать роли конкретного пользователя. Давайте сделаем так, чтобы наша страница включала варианты отображения как по ролям, так и по пользователям.
Начнем с создания пользовательского интерфейса. Этот интерфейс будет состоять из раскрывающегося списка и списка флажков. Раскрывающийся список будет заполнен набором пользователей в системе; Флажки перечисляют роли. При выборе пользователя из раскрывающегося списка будут отмечены те роли, к которым принадлежит пользователь. После этого пользователь, посещающий страницу, может проверить или снять флажки, чтобы добавить или удалить выбранного пользователя из соответствующих ролей.
Замечание
Использование раскрывающегося списка для перечисления учетных записей пользователей не является идеальным выбором для веб-сайтов, где могут быть сотни учетных записей пользователей. Раскрывающийся список предназначен для того, чтобы пользователь выбрал один элемент из относительно короткого списка параметров. Он быстро становится неудобным в использовании по мере роста числа элементов списка. Если вы создаете веб-сайт, который будет иметь потенциально большое количество учетных записей пользователей, вы можете рассмотреть возможность использования альтернативного пользовательского интерфейса, например страницы GridView или фильтруемого интерфейса, который предлагает посетителю выбрать букву, а затем отображать только тех пользователей, имя пользователя которых начинается с выбранной буквы.
Шаг 1. Построение пользовательского интерфейса "По пользователю"
Откройте страницу UsersAndRoles.aspx . В верхней части страницы добавьте элемент управления Label Web с именем ActionStatus и удалите его Text свойство. Мы будем использовать эту метку для предоставления отзывов о выполненных действиях, отображая такие сообщения, как "Пользователь Tito был добавлен в роль администраторов", или "Пользователь Jisun был удален из роли руководителей". Чтобы выделить эти сообщения, задайте для свойства Label CssClass значение "Важно".
<p align="center">
<asp:Label ID="ActionStatus" runat="server" CssClass="Important"></asp:Label>
</p>
Затем добавьте следующее определение класса CSS в таблицу стилей Styles.css :
.Important
{
font-size: large;
color: Red;
}
Это определение CSS указывает браузеру отображать метку с помощью большого красного шрифта. На рисунке 1 показан этот эффект с помощью конструктора Visual Studio.
Рис. 1. Свойство метки CssClass приводит к большому красному шрифту (щелкните, чтобы просмотреть изображение полного размера)
Затем добавьте DropDownList на страницу, задайте для его свойства ID значение UserList, и задайте для его свойства AutoPostBack значение True. Мы будем использовать этот раскрывающийся список, чтобы перечислить всех пользователей в системе. Этот выпадающий список будет привязан к коллекции объектов MembershipUser. Так как мы хотим, чтобы DropDownList отображал свойство UserName из объекта MembershipUser (и использовать его в качестве значения элементов списка), установите для свойств DataTextField и DataValueField раскрывающегося списка значение "UserName".
Под раскрывающимся списком добавьте повторитель с именем UsersRoleList. Этот компонент повтора будет перечислять все роли в системе в виде серии флажков. Определите повторитель ItemTemplate с помощью следующей декларативной разметки:
<asp:Repeater ID="UsersRoleList" runat="server">
<ItemTemplate>
<asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true"
Text='<%# Container.DataItem %>' />
<br />
</ItemTemplate>
</asp:Repeater>
Разметка ItemTemplate включает один элемент управления CheckBox Web.RoleCheckBox Свойство CheckBox AutoPostBack имеет значение True, а Text свойство привязано к Container.DataItem. Причина того, что синтаксис привязки данных просто Container.DataItem, заключается в том, что фреймворк ролей возвращает список имен ролей в виде строкового массива, и именно этот массив строк мы будем привязывать к повторителю. Подробное описание того, почему этот синтаксис используется для отображения содержимого массива, привязанного к веб-элементу управления данными, выходит за рамки этого руководства. Дополнительные сведения об этом вопросе см. в статье Привязка скалярного массива к веб-элементу управления данными.
На этом этапе декларативная разметка интерфейса "от пользователя" должна выглядеть примерно так:
<h3>Manage Roles By User</h3>
<p>
<b>Select a User:</b>
<asp:DropDownList ID="UserList" runat="server" AutoPostBack="True"
DataTextField="UserName" DataValueField="UserName">
</asp:DropDownList>
</p>
<p>
<asp:Repeater ID="UsersRoleList" runat="server">
<ItemTemplate>
<asp:CheckBox runat="server" ID="RoleCheckBox" AutoPostBack="true"
Text='<%# Container.DataItem %>' />
<br />
</ItemTemplate>
</asp:Repeater>
</p>
Теперь мы готовы написать код для привязки набора учетных записей пользователей к DropDownList и набору ролей к повторителю. В классе кода страницы добавьте метод с именем BindUsersToUserList и другим именем BindRolesList, используя следующий код:
private void BindUsersToUserList()
{
// Get all of the user accounts
MembershipUserCollection users = Membership.GetAllUsers();
UserList.DataSource = users;
UserList.DataBind();
}
private void BindRolesToList()
{
// Get all of the roles
string[] roles = Roles.GetAllRoles();
UsersRoleList.DataSource = roles;
UsersRoleList.DataBind();
}
Метод BindUsersToUserList извлекает все учетные записи пользователей в системе с помощью метода Membership.GetAllUsers.
MembershipUserCollection Возвращает объект, являющийся коллекцией экземпляровMembershipUser. Затем эта коллекция привязана к UserList DropDownList. Экземпляры MembershipUser, которые составляют коллекцию, содержат различные свойства, такие как UserName, Email, CreationDate и IsOnline. Чтобы указать DropDownList отображать значение свойства UserName, убедитесь, что свойства UserList и DataValueField для раскрывающегося списка имеют значение "UserName".
Замечание
Метод Membership.GetAllUsers имеет две перегрузки: тот, который принимает входные параметры и возвращает всех пользователей, и тот, который принимает целые значения для индекса страницы и размера страницы, и возвращает только указанное подмножество пользователей. Если в элементе пользовательского интерфейса отображается большое количество учетных записей пользователей, то для более эффективной страницы можно использовать вторую перегрузку, так как она возвращает только точное подмножество учетных записей пользователей, а не все из них.
Метод BindRolesToList начинается с вызова Roles метода классаGetAllRoles, который возвращает строковый массив, содержащий роли в системе. Затем этот массив строк привязан к повторителеру.
Наконец, необходимо вызвать эти два метода при первой загрузке страницы. Добавьте следующий код в Page_Load обработчик событий:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
}
}
Используя этот код, перейдите на страницу через браузер; экран должен выглядеть примерно так, как на рис. 2. Все учетные записи пользователей заполняются в раскрывающемся списке, и под ним каждая роль отображается как флажок. Поскольку свойства DropDownList и CheckBoxes установлены AutoPostBack как True, изменение выбранного пользователя или выбор/снятие выбора роли вызывает обратную передачу данных на сервер. Однако никаких действий не выполняется, так как нам еще не нужно писать код для обработки этих действий. Мы рассмотрим эти задачи в следующих двух разделах.
Рис. 2. На странице отображаются пользователи и роли (щелкните, чтобы просмотреть изображение полного размера)
Проверка ролей, к которым принадлежит выбранный пользователь
При первой загрузке страницы или при выборе нового пользователя из раскрывающегося списка необходимо обновить флажки UsersRoleList, чтобы флажок соответствующей роли был установлен только в том случае, если выбранный пользователь принадлежит этой роли. Для этого создайте метод с именем CheckRolesForSelectedUser со следующим кодом:
private void CheckRolesForSelectedUser()
{
// Determine what roles the selected user belongs to
string selectedUserName = UserList.SelectedValue;
string[] selectedUsersRoles = Roles.GetRolesForUser(selectedUserName);
// Loop through the Repeater's Items and check or uncheck the checkbox as needed
foreach (RepeaterItem ri in UsersRoleList.Items)
{
// Programmatically reference the CheckBox
CheckBox RoleCheckBox = ri.FindControl("RoleCheckBox") as CheckBox;
// See if RoleCheckBox.Text is in selectedUsersRoles
if (selectedUsersRoles.Contains<string>(RoleCheckBox.Text))
RoleCheckBox.Checked = true;
else
RoleCheckBox.Checked = false;
}
}
Приведенный выше код начинается с определения того, кто является выбранным пользователем. Затем он использует метод класса GetRolesForUser(userName) ролей для возврата указанного набора ролей пользователя в виде строкового массива. Далее перечисляются элементы повтора, и на флажок (CheckBox) каждого элемента программно делается ссылка. флажок установлен только в том случае, если соответствующая роль содержится в массиве строк selectedUsersRoles.
Замечание
Синтаксис selectedUserRoles.Contains<string>(...) не будет компилироваться, если используется ASP.NET версии 2.0. Метод Contains<string> является частью библиотеки LINQ, которая является новой для ASP.NET 3.5. Если вы по-прежнему используете ASP.NET версии 2.0, используйте метод Array.IndexOf<string> вместо этого.
Метод CheckRolesForSelectedUser должен вызываться в двух случаях: при первой загрузке страницы и при UserList изменении выбранного индекса DropDownList. Поэтому вызовите этот метод из обработчика Page_Load событий (после вызовов BindUsersToUserList и BindRolesToList). Кроме того, создайте обработчик событий для события DropDownList SelectedIndexChanged и вызовите этот метод.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
// Check the selected user's roles
CheckRolesForSelectedUser();
}
}
...
protected void UserList_SelectedIndexChanged(object sender, EventArgs e)
{
CheckRolesForSelectedUser();
}
С помощью этого кода можно протестировать страницу через браузер. Тем не менее, так как в UsersAndRoles.aspx настоящее время страница не имеет возможности назначать пользователей ролям, у пользователей нет ролей. Мы создадим интерфейс для назначения ролей пользователям в данный момент, чтобы вы могли либо принять мое слово, что этот код работает, и убедиться, что он делает это позже, либо вы можете вручную добавить пользователей в роли, вставив записи в aspnet_UsersInRoles таблицу, чтобы проверить эту функциональность сейчас.
Назначение и удаление пользователей из ролей
Когда посетитель проверяет или отменяет флажок в повторяющемся объекте UsersRoleList , необходимо добавить или удалить выбранного пользователя из соответствующей роли. Свойство CheckBox AutoPostBack в настоящее время имеет значение True, что вызывает обратную передачу в любое время, когда флажок в повторитее установлен или снят. Короче говоря, необходимо создать обработчик событий для события CheckBox CheckChanged . Поскольку флажок находится в элементе управления Repeater, необходимо вручную добавить основу для обработчика событий. Начните с добавления обработчика событий в класс code-behind в качестве protected метода, например:
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
}
Мы вернемся к написанию кода для этого обработчика событий в данный момент. Но сначала давайте завершим реализацию инфраструктуры для обработки событий. В CheckBox внутри элемента "Repeater" добавьте OnCheckedChanged="RoleCheckBox_CheckChanged". Этот синтаксис связывает обработчик событий RoleCheckBox_CheckChanged с событием CheckedChanged элемента RoleCheckBox.
<asp:CheckBox runat="server" ID="RoleCheckBox"
AutoPostBack="true"
Text='<%# Container.DataItem %>'
OnCheckedChanged="RoleCheckBox_CheckChanged" />
Наша окончательная задача — завершить RoleCheckBox_CheckChanged обработчик событий. Мы должны начать с ссылки на элемент управления CheckBox, который вызвал событие, так как этот экземпляр CheckBox сообщает нам, какая роль была проверена или снята с помощью его Text и Checked свойств. Используя эти сведения вместе с именем пользователя выбранного пользователя, мы добавляем или удаляем пользователя из роли с помощью Roles класса AddUserToRole или RemoveUserFromRole метода.
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
// Reference the CheckBox that raised this event
CheckBox RoleCheckBox = sender as CheckBox;
// Get the currently selected user and role
string selectedUserName = UserList.SelectedValue;
string roleName = RoleCheckBox.Text;
// Determine if we need to add or remove the user from this role
if (RoleCheckBox.Checked)
{
// Add the user to the role
Roles.AddUserToRole(selectedUserName, roleName);
// Display a status message
ActionStatus.Text = string.Format("User {0} was added to role {1}.", selectedUserName, roleName);
}
else
{
// Remove the user from the role
Roles.RemoveUserFromRole(selectedUserName, roleName);
// Display a status message
ActionStatus.Text = string.Format("User {0} was removed from role {1}.", selectedUserName, roleName);
}
}
Начало этого кода предполагает программное обращение к элементу CheckBox, который инициировал событие и доступен через входной параметр sender. Если установлен флажок, выбранный пользователь добавляется в указанную роль, в противном случае они удаляются из роли. Метка ActionStatus отображает сообщение, кратко описывающее только что выполненное действие.
Проверьте эту страницу через браузер. Выберите пользователя Tito, а затем добавьте Tito в роли "Администраторы" и "Руководители".
Рис. 3. Tito был добавлен к ролям администраторов и руководителей (щелкните, чтобы просмотреть изображение полного размера)
Затем выберите пользователя Брюса из раскрывающегося списка. Есть постбэк, и флажковые кнопки в элементе управления Repeater обновляются с помощью CheckRolesForSelectedUser. Так как Брюс еще не принадлежит ни к одной роли, оба флажка не отмечены. Затем добавьте Брюса в роль "Руководители".
Рис. 4. Брюса добавили в роль супервайзера (Щелкните, чтобы просмотреть изображение полного размера)
Чтобы дополнительно проверить функциональные возможности метода CheckRolesForSelectedUser, выберите пользователя, который не является Tito или Bruce. Обратите внимание, как флажки снимаются автоматически, что указывает на то, что они не принадлежат ни одной роли. Вернитесь в Тито. Убедитесь, что установлены флажки "Администраторы" и "Руководители".
Шаг 2. Создание пользовательского интерфейса "По ролям"
На этом этапе мы завершили интерфейс "по пользователям" и готовы начать решение интерфейса "по ролям". Интерфейс "по ролям" предложит пользователю выбрать роль из раскрывающегося списка, а затем отображает набор пользователей, принадлежащих этой роли в GridView.
Добавьте на страницу UsersAndRoles.aspx еще один элемент управления DropDownList. Поместите этот объект под элементом управления Repeater, присвойте ему RoleListимя и задайте для него AutoPostBack значение True. Под этим добавьте GridView и присвойте ему RolesUserListимя. Этот GridView выводит список пользователей, принадлежащих выбранной роли. Задайте для свойства GridView AutoGenerateColumns значение False, добавьте TemplateField в коллекцию сетки Columns и задайте его свойство HeaderText на «Users». Определите имя TemplateField ItemTemplate таким образом, чтобы оно отображало значение выражения Container.DataItem привязки данных в Text свойстве метки с именем UserNameLabel.
После добавления и настройки GridView декларативная разметка интерфейса "by role" должна выглядеть следующим образом:
<h3>Manage Users By Role</h3>
<p>
<b>Select a Role:</b>
<asp:DropDownList ID="RoleList" runat="server" AutoPostBack="true"></asp:DropDownList>
</p>
<p> <asp:GridView ID="RolesUserList" runat="server" AutoGenerateColumns="false"
EmptyDataText="No users belong to this role.">
<Columns>
<asp:TemplateField HeaderText="Users">
<ItemTemplate>
<asp:Label runat="server" id="UserNameLabel"
Text='<%# Container.DataItem %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView> </p>
Нам нужно заполнить RoleList DropDownList набором ролей в системе. Для этого обновите BindRolesToList метод таким образом, чтобы привязать массив строк, возвращаемый Roles.GetAllRoles методом, к RolesList DropDownList (а также UsersRoleList повторителю).
private void BindRolesToList()
{
// Get all of the roles
string[] roles = Roles.GetAllRoles();
UsersRoleList.DataSource = roles;
UsersRoleList.DataBind();
RoleList.DataSource = roles;
RoleList.DataBind();
}
Последние две строки в BindRolesToList методе добавлены для привязки набора ролей к элементу RoleList управления DropDownList. На рисунке 5 показан конечный результат при просмотре через браузер — раскрывающийся список, заполненный ролями системы.
Рис. 5. Роли отображаются в раскрывающемся RoleList списке (щелкните, чтобы просмотреть изображение полного размера)
Отображение пользователей, принадлежащих выбранной роли
При первой загрузке страницы или при выборе новой роли из RoleList DropDownList необходимо отобразить список пользователей, принадлежащих этой роли в GridView. Создайте метод с именем DisplayUsersBelongingToRole , используя следующий код:
private void DisplayUsersBelongingToRole()
{
// Get the selected role
string selectedRoleName = RoleList.SelectedValue;
// Get the list of usernames that belong to the role
string[] usersBelongingToRole = Roles.GetUsersInRole(selectedRoleName);
// Bind the list of users to the GridView
RolesUserList.DataSource = usersBelongingToRole;
RolesUserList.DataBind();
}
Этот метод начинается с получения выбранной роли из RoleList DropDownList. Затем он использует Roles.GetUsersInRole(roleName) метод для получения строкового массива имен пользователей, принадлежащих этой роли. Затем этот массив привязан к RolesUserList GridView.
Этот метод должен вызываться в двух случаях: когда страница изначально загружается и когда выбранная роль в RoleList DropDownList изменяется. Поэтому обновите Page_Load обработчик событий таким образом, чтобы этот метод был вызван после вызова CheckRolesForSelectedUser. Затем создайте обработчик событий для RoleListSelectedIndexChanged события и вызовите этот метод.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Bind the users and roles
BindUsersToUserList();
BindRolesToList();
// Check the selected user's roles
CheckRolesForSelectedUser();
// Display those users belonging to the currently selected role
DisplayUsersBelongingToRole();
}
}
...
protected void RoleList_SelectedIndexChanged(object sender, EventArgs e)
{
DisplayUsersBelongingToRole();
}
В этом коде в RolesUserList GridView должны отображаться те пользователи, которые принадлежат выбранной роли. Как показано на рисунке 6, роль "руководителей" исполняют два человека: Брюс и Тито.
Рис. 6. GridView выводит список тех пользователей, которые относятся к выбранной роли (щелкните, чтобы просмотреть изображение полного размера)
Удаление пользователей из выбранной роли
Давайте расширим RolesUserList GridView, чтобы он включал столбец кнопок "Удалить". При нажатии кнопки "Удалить" для конкретного пользователя они будут удалены из этой роли.
Начните с добавления поля кнопки "Удалить" в GridView. Убедитесь, что это поле отображается в самом левом положении, и измените его DeleteText свойство с "Удалить" (по умолчанию) на "Убрать".
Рис. 7. Добавление кнопки "Удалить" в GridView (щелкните, чтобы просмотреть изображение полного размера)
После нажатия кнопки "Удалить" происходит обратная связь и возникает событие GridView RowDeleting . Необходимо создать обработчик событий для этого события и написать код, который удаляет пользователя из выбранной роли. Создайте обработчик событий и добавьте следующий код:
protected void RolesUserList_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
// Get the selected role
string selectedRoleName = RoleList.SelectedValue;
// Reference the UserNameLabel
Label UserNameLabel = RolesUserList.Rows[e.RowIndex].FindControl("UserNameLabel") as Label;
// Remove the user from the role
Roles.RemoveUserFromRole(UserNameLabel.Text, selectedRoleName);
// Refresh the GridView
DisplayUsersBelongingToRole();
// Display a status message
ActionStatus.Text = string.Format("User {0} was removed from role {1}.", UserNameLabel.Text, selectedRoleName);
}
Код начинается с определения имени выбранной роли. Затем она программно ссылается на UserNameLabel элемент управления из строки, кнопка "Удалить" на которую была нажата, чтобы определить имя пользователя, которого нужно удалить. Затем пользователь удаляется из роли с помощью вызова Roles.RemoveUserFromRole метода. Затем RolesUserList gridView обновляется, и сообщение отображается с помощью ActionStatus элемента управления Label.
Замечание
Кнопка "Удалить" не требует подтверждения от пользователя перед удалением пользователя из роли. Я приглашаю вас добавить некоторый уровень подтверждения пользователя. Одним из самых простых способов подтверждения действия является диалоговое окно подтверждения на стороне клиента. Дополнительные сведения об этом методе см. в разделе "Добавление подтверждения Client-Side при удалении".
На рисунке 8 показана страница после удаления пользователя Tito из группы "Руководители".
Рис. 8. Увы, Tito больше не является руководителем (щелкните, чтобы просмотреть изображение полного размера)
Добавление новых пользователей в выбранную роль
Наряду с удалением пользователей из выбранной роли посетитель этой страницы также должен иметь возможность добавить пользователя в выбранную роль. Лучший интерфейс для добавления пользователя в выбранную роль зависит от количества учетных записей пользователей, которые вы ожидаете. Если ваш веб-сайт будет размещать всего несколько десятков учетных записей пользователей или меньше, вы можете использовать dropDownList здесь. Если может быть тысячи учетных записей пользователей, вы хотите включить пользовательский интерфейс, позволяющий посетителю просматривать страницы через учетные записи, искать определенную учетную запись или фильтровать учетные записи пользователей в другом виде.
На этой странице давайте используем очень простой интерфейс, который работает независимо от количества учетных записей пользователей в системе. А именно, мы будем использовать TextBox, предлагая посетителю ввести имя пользователя пользователя, который она хочет добавить в выбранную роль. Если пользователь с таким именем не существует, или если пользователь уже является членом роли, мы отобразим сообщение в ActionStatus Label. Но если пользователь существует и не является членом роли, мы добавим их в роль и обновим сетку.
Добавьте текстовое поле и кнопку под GridView. Задайте для TextBox свойства ID и UserNameToAddToRole, а также задайте для кнопки свойства ID и Text значение AddUserToRoleButton и "Добавить пользователя в роль" соответственно.
<p>
<b>UserName:</b>
<asp:TextBox ID="UserNameToAddToRole" runat="server"></asp:TextBox>
<br />
<asp:Button ID="AddUserToRoleButton" runat="server" Text="Add User to Role" />
</p>
Затем создайте Click обработчик событий для этого AddUserToRoleButton кода и добавьте следующий код:
protected void AddUserToRoleButton_Click(object sender, EventArgs e)
{
// Get the selected role and username
string selectedRoleName = RoleList.SelectedValue;
string userNameToAddToRole = UserNameToAddToRole.Text;
// Make sure that a value was entered
if (userNameToAddToRole.Trim().Length == 0)
{
ActionStatus.Text = "You must enter a username in the textbox.";
return;
}
// Make sure that the user exists in the system
MembershipUser userInfo = Membership.GetUser(userNameToAddToRole);
if (userInfo == null)
{
ActionStatus.Text = string.Format("The user {0} does not exist in the system.", userNameToAddToRole);
return;
}
// Make sure that the user doesn't already belong to this role
if (Roles.IsUserInRole(userNameToAddToRole, selectedRoleName))
{
ActionStatus.Text = string.Format("User {0} already is a member of role {1}.", userNameToAddToRole, selectedRoleName);
return;
}
// If we reach here, we need to add the user to the role
Roles.AddUserToRole(userNameToAddToRole, selectedRoleName);
// Clear out the TextBox
UserNameToAddToRole.Text = string.Empty;
// Refresh the GridView
DisplayUsersBelongingToRole();
// Display a status message
ActionStatus.Text = string.Format("User {0} was added to role {1}.", userNameToAddToRole, selectedRoleName); }
Большинство кода в обработчике Click событий выполняет различные проверки. Это гарантирует, что посетитель предоставил имя пользователя в UserNameToAddToRole TextBox, что пользователь существует в системе, и что он еще не принадлежит выбранной роли. Если какая-либо из этих проверок завершается сбоем, соответствующее сообщение отображается ActionStatus и обработчик событий завершается. Если все проверки проходят, пользователь добавляется в роль с помощью Roles.AddUserToRole метода. После этого свойство TextBox Text очищается, GridView обновляется, а ActionStatus Label отображает сообщение, указывающее, что данный пользователь успешно добавлен в выбранную роль.
Замечание
Чтобы убедиться, что указанный пользователь еще не принадлежит выбранной роли, мы используем Roles.IsUserInRole(userName, roleName) метод, который возвращает логическое значение, указывающее, является ли имя пользователя членом roleName. Мы будем использовать этот метод снова в , когда мы рассмотрим авторизацию на основе ролей.
Перейдите на страницу через браузер и выберите роль "Руководители" в раскрывающемся RoleList списке. Попробуйте ввести недопустимое имя пользователя— должно появиться сообщение, объясняющее, что пользователь не существует в системе.
Рис. 9. Невозможно добавить несуществующего пользователя в роль (щелкните, чтобы просмотреть изображение полного размера)
Теперь попробуйте добавить допустимого пользователя. Повторно добавьте Tito в роль "Руководители".
Рис. 10. Тито снова является руководителем! (Щелкните, чтобы просмотреть изображение полного размера)
Шаг 3. Перекрестное обновление интерфейсов "По пользователю" и "По роли"
Страница UsersAndRoles.aspx предлагает два различных интерфейса для управления пользователями и ролями. В настоящее время эти два интерфейса действуют независимо друг от друга, поэтому возможно, что изменения, внесенные в одном интерфейсе, не будут отражены немедленно в другом. Например, представьте, что посетитель страницы выбирает роль "Руководители" из выпадающего списка RoleList, в котором в качестве членов перечислены Брюс и Тито. Затем посетитель выбирает Tito из UserList раскрывающегося списка, который проверяет флажки "Администраторы и руководители" в UsersRoleList повторителе. Если посетитель снимет флажок роли "Руководитель" из Repeater, Tito удалится из роли "Руководители", но это изменение не отражается в интерфейсе «По ролям». GridView по-прежнему показывает, что Tito является членом роли "Руководители".
Чтобы устранить эту проблему, необходимо обновлять GridView всякий раз, когда в UsersRoleList Repeater отмечается или снимается отметка с роли. Аналогичным образом необходимо обновить повторитель всякий раз, когда пользователь удаляется или добавляется в роль из интерфейса "по ролям".
Повторитель в интерфейсе, доступном пользователю, обновляется методом CheckRolesForSelectedUser. Интерфейс "по роли" можно изменить в RolesUserList обработчике событий GridView RowDeleting и AddUserToRoleButton обработчике событий Button Click . Поэтому необходимо вызвать CheckRolesForSelectedUser метод из каждого из этих методов.
protected void RolesUserList_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
... Code removed for brevity ...
// Refresh the "by user" interface
CheckRolesForSelectedUser();
}
protected void AddUserToRoleButton_Click(object sender, EventArgs e)
{
... Code removed for brevity ...
// Refresh the "by user" interface
CheckRolesForSelectedUser();
}
Аналогичным образом GridView в интерфейсе "по ролям" обновляется путем вызова DisplayUsersBelongingToRole метода, а интерфейс "по пользователю" изменяется с помощью RoleCheckBox_CheckChanged обработчика событий. Поэтому необходимо вызвать DisplayUsersBelongingToRole метод из этого обработчика событий.
protected void RoleCheckBox_CheckChanged(object sender, EventArgs e)
{
... Code removed for brevity...
// Refresh the "by role" interface
DisplayUsersBelongingToRole();
}
При этих незначительных изменениях кода интерфейсы "по пользователю" и "по роли" теперь правильно обновляются. Чтобы проверить это, перейдите на страницу через браузер и выберите Tito и Супервизоры в раскрывающихся списках UserList и RoleList соответственно. Обратите внимание, что при снятии роли "Руководители" для Tito из элемента управления Repeater в интерфейсе "по пользователю" Tito автоматически удаляется из GridView в интерфейсе "по ролям". Добавление Tito обратно в роль "Руководители" из интерфейса "by role" автоматически проверяет флажок "Руководители" в пользовательском интерфейсе.
Шаг 4. Настройка CreateUserWizard для включения шага "Указать роли"
В руководстве по созданию учетных записей пользователей мы узнали, как использовать веб-элемент управления CreateUserWizard для создания новой учетной записи пользователя. Элемент управления CreateUserWizard можно использовать одним из двух способов:
- В качестве средства для посетителей создать собственную учетную запись пользователя на сайте и
- В качестве средства для администраторов для создания новых учетных записей
В первом случае использования посетитель приходит на сайт и заполняет CreateUserWizard, введя свои сведения для регистрации на сайте. Во втором случае администратор создает новую учетную запись для другого человека.
При создании учетной записи администратором для другого пользователя может потребоваться разрешить администратору указать, к каким ролям принадлежит новая учетная запись пользователя. В руководстве по хранениюдополнительных сведений о пользователе мы узнали, как настроить CreateUserWizard, добавив дополнительные WizardStepsсведения. Давайте рассмотрим, как добавить дополнительный шаг в CreateUserWizard, чтобы указать роли нового пользователя.
Откройте страницу CreateUserWizardWithRoles.aspx и добавьте элемент управления CreateUserWizard с именем RegisterUserWithRoles. Задайте для свойства элемента управления ContinueDestinationPageUrl значение ~/Default.aspx. Так как в этом случае администратор будет использовать этот элемент управления CreateUserWizard для создания учетных записей пользователей, задайте для свойства элемента управления LoginCreatedUser значение False. Это LoginCreatedUser свойство указывает, будет ли посетитель автоматически входить в систему как только что созданный пользователь, и по умолчанию используется значение True. Мы устанавливаем значение False, потому что, когда администратор создает новую учетную запись, мы хотим, чтобы он оставался в системе под своей учетной записью.
Затем выберите параметр "Добавить/Удалить WizardSteps…" из смарт-тега CreateUserWizard и добавьте новый WizardStep, задав его ID на SpecifyRolesStep. Переместите SpecifyRolesStep WizardStep так, чтобы он был после шага "Регистрация для новой учетной записи", но перед шагом "Завершить". Присвойте свойству Title элемента WizardStep значение "Указать роли", свойству Step элемента StepType значение Step, и свойству AllowReturn значение False.
Рис. 11. Добавьте "Указать роли" WizardStep в createUserWizard (щелкните, чтобы просмотреть изображение полного размера)
После этого изменения декларативная разметка CreateUserWizard должна выглядеть следующим образом:
<asp:CreateUserWizard ID="RegisterUserWithRoles" runat="server"
ContinueDestinationPageUrl="~/Default.aspx" LoginCreatedUser="False">
<WizardSteps>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
</asp:CreateUserWizardStep>
<asp:WizardStep ID="SpecifyRolesStep" runat="server" StepType="Step"
Title="Specify Roles" AllowReturn="False">
</asp:WizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>
В поле "Указать роли" WizardStepдобавьте checkBoxList с именем RoleList. Этот CheckBoxList будет перечислять доступные роли, позволяя пользователю, посещающему страницу, проверить, к каким ролям принадлежит только что созданный пользователь.
Мы остаемся с двумя задачами написания кода: сначала необходимо заполнить RoleList CheckBoxList ролями в системе. Во-вторых, необходимо добавить созданного пользователя в выбранные роли при переходе пользователя с шага "Указать роли" на шаг "Завершить". Мы можем выполнить первую задачу в обработчике Page_Load событий. Приведенный ниже код программно обращается к CheckBox при первом посещении страницы и связывает с ним роли в системе.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Reference the SpecifyRolesStep WizardStep
WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;
// Reference the RoleList CheckBoxList
CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;
// Bind the set of roles to RoleList
RoleList.DataSource = Roles.GetAllRoles();
RoleList.DataBind();
}
}
Приведенный выше код должен выглядеть знакомым. В руководстве Хранениедополнительной информации о пользователе мы использовали два FindControl оператора для обращения к веб-элементу управления из пользовательского WizardStepэлемента управления. И код, который привязывает роли к CheckBoxList, был взят ранее в этом руководстве.
Чтобы выполнить вторую задачу программирования, необходимо знать, когда завершен шаг "Указать роли". Помните, что CreateUserWizard имеет ActiveStepChanged событие, которое запускается каждый раз, когда посетитель переходит от одного шага к другому. Здесь можно определить, достиг ли пользователь шага "Завершить"; В этом случае необходимо добавить пользователя в выбранные роли.
Создайте обработчик событий для ActiveStepChanged события и добавьте следующий код:
protected void RegisterUserWithRoles_ActiveStepChanged(object sender, EventArgs e)
{
// Have we JUST reached the Complete step?
if (RegisterUserWithRoles.ActiveStep.Title == "Complete")
{
// Reference the SpecifyRolesStep WizardStep
WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;
// Reference the RoleList CheckBoxList
CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;
// Add the checked roles to the just-added user
foreach (ListItem li in RoleList.Items)
{
if (li.Selected)
Roles.AddUserToRole(RegisterUserWithRoles.UserName, li.Text);
}
}
}
Если пользователь только что достиг шага "Завершено", обработчик событий перечисляет элементы RoleList CheckBoxList, а только что созданный пользователь назначается выбранным ролям.
Посетите эту страницу через браузер. Первый шаг в createUserWizard — это стандартный шаг "Регистрация для новой учетной записи", который запрашивает имя пользователя нового пользователя, пароль, электронную почту и другие ключевые сведения. Введите сведения для создания нового пользователя с именем Wanda.
Рис. 12. Создание пользователя с именем Wanda (щелкните, чтобы просмотреть изображение полного размера)
Нажмите кнопку "Создать пользователя". CreateUserWizard внутренне вызывает Membership.CreateUser метод, создав новую учетную запись пользователя, а затем переходит к следующему шагу "Указать роли". Здесь перечислены системные роли. Установите флажок "Руководители" и нажмите кнопку "Далее".
Рис. 13. Сделайте Ванду участником роли руководителей (щелкните, чтобы просмотреть изображение полного размера)
Нажатие кнопки "Далее" вызывает обратную отправку и обновляет ActiveStep, переводя его на шаг "Завершить". В обработчике ActiveStepChanged событий недавно созданная учетная запись пользователя назначается роли "Руководители". Чтобы проверить это, вернитесь на страницу UsersAndRoles.aspx и выберите "Руководители" в раскрывающемся списке RoleList . Как показано на рисунке 14, руководители теперь состоят из трех пользователей: Брюс, Тито и Ванда.
Рис. 14. Брюс, Тито и Ванда являются всеми руководителями (щелкните, чтобы просмотреть изображение полного размера)
Сводка
Платформа ролей предлагает методы получения сведений о ролях и методах конкретного пользователя для определения того, какие пользователи относятся к указанной роли. Кроме того, существует ряд методов добавления и удаления одного или нескольких пользователей в одну или несколько ролей. В этом руководстве мы сосредоточились только на двух из этих методов: AddUserToRole и RemoveUserFromRole. Существуют дополнительные варианты, предназначенные для добавления нескольких пользователей в одну роль и назначения нескольких ролей одному пользователю.
В этом руководстве также описано расширение элемента управления CreateUserWizard для включения WizardStep, чтобы указать роли вновь созданного пользователя. Такой шаг может помочь администратору упростить процесс создания учетных записей пользователей для новых пользователей.
На этом этапе мы видели, как создавать и удалять роли, а также как добавлять и удалять пользователей из ролей. Но мы еще не рассмотрели применение авторизации на основе ролей. В следующем руководстве мы рассмотрим определение правил авторизации URL-адресов на основе ролей, а также ограничение функциональных возможностей на уровне страницы на основе ролей пользователя, вошедшего в систему.
Счастливое программирование!
Дальнейшее чтение
Дополнительные сведения о разделах, описанных в этом руководстве, см. в следующих ресурсах:
Сведения о авторе
Скотт Митчелл, автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С Скоттом можно связаться на mitchell@4guysfromrolla.com или через его блог http://ScottOnWriting.NET.
Особое спасибо...
Эта серия учебников была проверена многими полезными рецензентами. Ведущий рецензент этого учебного пособия — Тереса Мерфи. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com