ASP.NET Identity в многоуровневой архитектуре. Часть 1

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

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

Ранее мы рассмотрели создание трехуровневой архитектуры приложения. Тепеь рассмотрим, как мы можем использовать в этой архитектуре встроенную систему аутентификации и авторизации ASP.NET Identity.

Итак, создадим новое решение. Пусть оно будет называться UserStore и в этом решении определим новый проект UserStore.WEB по типу ASP.NET MVC 5 без аутентификации.

ASP.NET Identity in NLayer Architecture

После этого добавим в решение новый проект по типу Class Library, который назовем UserStore.DAL. Этот проект будет представлять слой доступа к данным.

Так как мы будем использовать систему ASP.NET Identity, то нам вначале надо добавить соответствующие пакеты NuGet: EntityFramework, Microsoft.AspNet.Identity.Core и Microsoft.AspNet.Identity.EntityFramework

ASP.NET Identity Core в многоуровневой архитектуре

Вначале добавим в DAL-проект новую папку, которую назовем Entities. В этой папке будут храниться сущности приложения. В данном случае ограничимся тремя сущностями: классом пользователя, классом роли и классом профиля пользователя.

Итак, добавим в папку Entities новый класс ApplicationUser:

using Microsoft.AspNet.Identity.EntityFramework;

namespace UserStore.DAL.Entities
{
    public class ApplicationUser : IdentityUser
    {
        public virtual ClientProfile ClientProfile { get; set; }
    }
}

И также добавим класс профиля пользователя ClientProfile:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace UserStore.DAL.Entities
{
    public class ClientProfile
    {
        [Key]
        [ForeignKey("ApplicationUser")]
        public string Id { get; set; }

        public string Name { get; set; }
        public string Address { get; set; }

        public virtual ApplicationUser ApplicationUser { get; set; }
    }
}

Класс пользователя и его профиля связаны отношением один-к-одному. Разделение данных о пользователя на два класса позволит независимо друг от друга рассматривать аутентификационные данные и вспомогательные данные, то есть профиль пользователя, которые не играют никакой роли при аутентификации.

И также добавим в эту папку класс роли ApplicationRole:

using Microsoft.AspNet.Identity.EntityFramework;

namespace UserStore.DAL.Entities
{
    public class ApplicationRole : IdentityRole
    {
    }
}

Важно отметить, что эти классы зависят от пространства имен Microsoft.AspNet.Identity.EntityFramework.

Далее добавим в проект новую папку, которую назовем EF и в которую поместим новый класс ApplicationContext, то есть контекст данных:

using System.Data.Entity;
using Microsoft.AspNet.Identity.EntityFramework;
using UserStore.DAL.Entities;

namespace UserStore.DAL.EF
{
    public class ApplicationContext: IdentityDbContext<ApplicationUser>
    {
        public ApplicationContext(string conectionString) : base(conectionString) { }

        public DbSet<ClientProfile> ClientProfiles { get; set; }
    }
}

Данный класс наследуется от класса IdentityDbContext и поэтому уже имеет свойства Users и Roles, позволяющие взаимодействовать с таблицами пользователей и ролей. Поэтому здесь мы добавляем только свойство для ClientProfile.

Теперь добавим в проект еще три папки: Identity, Interfaces и Repositories. В папку Identity добавим класс ApplicationUserManager:

using UserStore.DAL.Entities;
using Microsoft.AspNet.Identity;

namespace UserStore.DAL.Identity
{
    public class ApplicationUserManager : UserManager<ApplicationUser>
    {
        public ApplicationUserManager(IUserStore<ApplicationUser> store)
                : base(store)
        {
        }
    }
}

Данный класс будет управлять пользователями: добавлять их в базу данных и аутентифицировать.

Также добавим в папку Identity новый класс ApplicationRoleManager:

using UserStore.DAL.Entities;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace UserStore.DAL.Identity
{
    public class ApplicationRoleManager : RoleManager<ApplicationRole>
    {
        public ApplicationRoleManager(RoleStore<ApplicationRole> store)
                    : base(store)
        { }
    }
}

Это стандартные для ASP.NET Identity классы по управлению ролями и пользователями. По сути эти классы выполняют роль репозиториев.

В папку Interfaces добавим интерфейс управления профилями пользователей IClientManager:

using UserStore.DAL.Entities;
using System;

namespace UserStore.DAL.Interfaces
{
    public interface IClientManager:IDisposable
    {
        void Create(ClientProfile item);
    }
}

Данный интерфейс содержит один метод для создания нового профиля пользователя.

И также определим интерфейс для UnitOfWork:

using UserStore.DAL.Identity;
using System;
using System.Threading.Tasks;

namespace UserStore.DAL.Interfaces
{
    public interface IUnitOfWork : IDisposable
    {
        ApplicationUserManager UserManager { get; }
        IClientManager ClientManager { get; }
        ApplicationRoleManager RoleManager { get; }
        Task SaveAsync();
    }
}

Объект UnitOfWork будет содержать ссылки на менеджеры пользователей и ролей, а также на репозиторий пользователей.

В папку Repositories добавим два класса - конкретные реализации этих интерфейсов. Класс управления профилями ClientManager:

using UserStore.DAL.EF;
using UserStore.DAL.Entities;
using UserStore.DAL.Interfaces;

namespace UserStore.DAL.Repositories
{
    public class ClientManager : IClientManager
    {
        public ApplicationContext Database { get; set; }
        public ClientManager(ApplicationContext db)
        {
            Database = db;
        }

        public void Create(ClientProfile item)
        {
            Database.ClientProfiles.Add(item);
            Database.SaveChanges();
        }

        public void Dispose()
        {
            Database.Dispose();
        }
    }
}

И класс IdentityUnitOfWork:

using UserStore.DAL.EF;
using UserStore.DAL.Entities;
using UserStore.DAL.Interfaces;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Threading.Tasks;
using UserStore.DAL.Identity;

namespace UserStore.DAL.Repositories
{
    public class IdentityUnitOfWork : IUnitOfWork
    {
        private ApplicationContext db;

        private ApplicationUserManager userManager;
        private ApplicationRoleManager roleManager;
        private IClientManager clientManager;

        public IdentityUnitOfWork(string connectionString)
        {
            db = new ApplicationContext(connectionString);
            userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(db));
            roleManager = new ApplicationRoleManager(new RoleStore<ApplicationRole>(db));
            clientManager = new ClientManager(db);
        }

        public ApplicationUserManager UserManager
        {
            get { return userManager; }
        }

        public IClientManager ClientManager
        {
            get { return clientManager; }
        }

        public ApplicationRoleManager RoleManager
        {
            get { return roleManager; }
        }

        public async Task SaveAsync()
        {
            await db.SaveChangesAsync();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        private bool disposed = false;

        public virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    userManager.Dispose();
                    roleManager.Dispose();
                    clientManager.Dispose();
                }
                this.disposed = true;
            }
        }
    }
}

Класс инкапсулирует все менеджеры для работы с сущностями в виде свойств и хранит общий контекст данных.

В итоге проект будет выглядеть следующим образом:

Data Access Layer in ASP.NET Identity
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850