Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Сущность ролей в ASP.NET Identity представлена классом IdentityRole, который реализует интерфейс IRole. И мы можем продолжать использовать IdentityRole, но при необходимости также можем переопределить, добавив в него новые свойства. Итак, возьмем проект из прошлой темы и добавим в него функциональность управления ролями.
Для начала добавим в папку Models новый класс ApplicationRole:
using Microsoft.AspNet.Identity.EntityFramework; public class ApplicationRole: IdentityRole { public ApplicationRole(){} public string Description { get; set; } }
Новый класс наследует весь функционал от IdentityRole плюс добавляет новое свойство Description
, которое будет содержать описание роли.
Для управления ролями используется менеджер ролей RoleManager. Поэтому добавим в папку Models новый класс ApplicationRoleManager:
class ApplicationRoleManager : RoleManager<ApplicationRole> { public ApplicationRoleManager(RoleStore<ApplicationRole> store) : base(store) {} public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context) { return new ApplicationRoleManager(new RoleStore<ApplicationRole>(context.Get<ApplicationContext>())); } }
Опять же наследуем функционал от уже имеющегося класса RoleManager. Метод Create
позволит классу приложения OWIN создавать
экземпляры менеджера ролей для обработки каждого запроса, где идет обращение к хранилищу ролей RoleStore.
И теперь нам надо зарегистрировать менеджер ролей в классе приложения OWIN. Поэтому откроем файл Startup.cs, который по предыдущим темам у нас находился в папке App_Start, и изменим его содержимое следующим образом:
public class Startup { public void Configuration(IAppBuilder app) { app.CreatePerOwinContext<ApplicationContext>(ApplicationContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); // регистрация менеджера ролей app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), }); } }
Благодаря регистрации менеджер ролей будет использовать тот же контекст данных, что и менеджер пользователей.
Если мы создаем систему ролей в приложении после первого запуска приложения, то нам надо будет произвести миграцию, так как контекст данных у нас изменился в силу изменения системы ролей. Поэтому в Visual Studio в окне Package Manager Console введем команду: enable-migrations и нажмем Enter.
Теперь нам надо создать саму миграцию. Там же в консоли Package Manager Console введем команду:
PM> Add-Migration "DataMigration"
Visual Studio автоматически сгенерирует класс миграции:
public partial class DataMigration : DbMigration { public override void Up() { AddColumn("dbo.AspNetRoles", "Description", c => c.String()); AddColumn("dbo.AspNetRoles", "Discriminator", c => c.String(nullable: false, maxLength: 128)); } public override void Down() { DropColumn("dbo.AspNetRoles", "Discriminator"); DropColumn("dbo.AspNetRoles", "Description"); } }
И чтобы выполнить миграцию, применим этот класс, набрав в той же консоли команду:
PM> Update-Database
Теперь создадим контроллер, который будет выполнять стандартные действия с ролями:
using AspNetIdentityApp.Models; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; public class RolesController : Controller { private ApplicationRoleManager RoleManager { get { return HttpContext.GetOwinContext().GetUserManager<ApplicationRoleManager>(); } } public ActionResult Index() { return View(RoleManager.Roles); } public ActionResult Create() { return View(); } [HttpPost] public async Task<ActionResult> Create(CreateRoleModel model) { if (ModelState.IsValid) { IdentityResult result = await RoleManager.CreateAsync(new ApplicationRole { Name = model.Name, Description = model.Description }); if (result.Succeeded) { return RedirectToAction("Index"); } else { ModelState.AddModelError("", "Что-то пошло не так"); } } return View(model); } public async Task<ActionResult> Edit(string id) { ApplicationRole role = await RoleManager.FindByIdAsync(id); if (role != null) { return View(new EditRoleModel { Id = role.Id, Name = role.Name, Description = role.Description }); } return RedirectToAction("Index"); } [HttpPost] public async Task<ActionResult> Edit(EditRoleModel model) { if (ModelState.IsValid) { ApplicationRole role = await RoleManager.FindByIdAsync(model.Id); if (role != null) { role.Description = model.Description; role.Name = model.Name; IdentityResult result = await RoleManager.UpdateAsync(role); if (result.Succeeded) { return RedirectToAction("Index"); } else { ModelState.AddModelError("", "Что-то пошло не так"); } } } return View(model); } public async Task<ActionResult> Delete(string id) { ApplicationRole role = await RoleManager.FindByIdAsync(id); if (role != null) { IdentityResult result = await RoleManager.DeleteAsync(role); } return RedirectToAction("Index"); } }
Это стандартный CRUD-контроллер, выполняющий чтение, удаление, редактирование и добавление ролей. Вначале для взаимодействия с менеджером ролей мы получаем его объект из контекста OWIN:
HttpContext.GetOwinContext().GetUserManager<ApplicationRoleManager>()
Затем методы менеджера ролей используются для управления ролями. Обратите внимание, что из представлений в методы Create и Edit мы получаем не объект ApplicationRole, а специальные модели EditRoleModel и CreateRoleModel, который могут выглядеть так:
public class EditRoleModel { public string Id { get; set; } public string Name { get; set; } public string Description { get; set; } } public class CreateRoleModel { public string Name { get; set; } public string Description { get; set; } }
Использование моделей позволит избежать различных проблем с контекстом данных и управлением объектами, которые могли возникнуть, если бы мы напрямую использовали бы ApplicationRole.
И представления будут выглядеть стандартно. Представление Index.cshtml:
@model IEnumerable<AspNetIdentityApp.Models.ApplicationRole> @{ ViewBag.Title = "Роли"; } <h2>Роли</h2> <table class="table"> <tr> <th>Название</th> <th>Описание</th> <th></th> </tr> @foreach (var item in Model) { <tr> <td>@item.Name</td> <td>@item.Description</td> <td> @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | @Html.ActionLink("Delete", "Delete", new { id=item.Id }) </td> </tr> } </table>
Представление Create.cshtml:
@model AspNetIdentityApp.Models.CreateRoleModel <h2>Добавление роли</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div> @Html.ValidationSummary(true, "") <p>Название: @Html.EditorFor(model => model.Name)</p> <p>Описание: @Html.EditorFor(model => model.Description)</p> <p><input type="submit" value="Добавить" /></p> </div> }
И представление для редактирования Edit.cshtml:
@model AspNetIdentityApp.Models.EditRoleModel <h2>Редактирование роли</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div> @Html.ValidationSummary(true, "") @Html.HiddenFor(model => model.Id) <p>Название: @Html.EditorFor(model => model.Name)</p> <p>Описание: @Html.EditorFor(model => model.Description)</p> <p><input type="submit" value="Изменить" /></p> </div> }