Добавление ролей в ASP.NET Identity

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 31.10.2015

Сущность ролей в 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>
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850