C# ASP.NET标识角色已退出

C# ASP.NET标识角色已退出,c#,asp.net,asp.net-identity,asp.net-roles,role-manager,C#,Asp.net,Asp.net Identity,Asp.net Roles,Role Manager,我正在构建一个多租户应用程序。因此,我添加了一个名为OwnerId(角色所有者)的列。我在使用ASP.NET标识向AspNetRoles表添加角色时遇到一些问题 我有一个自定义的RoleValidator,每次评估都会成功。但是,SaveChangesSync失败:角色已存在 我已经更改了AspNetRoles RoleNameIndex以适应Name和OwnerId,但是SaveChangesSync仍然失败 我查看了这个线程,但已经实现了这些更正: ApplicationRoleStore

我正在构建一个多租户应用程序。因此,我添加了一个名为OwnerId(角色所有者)的列。我在使用ASP.NET标识向AspNetRoles表添加角色时遇到一些问题

我有一个自定义的RoleValidator,每次评估都会成功。但是,SaveChangesSync失败:角色已存在

我已经更改了AspNetRoles RoleNameIndex以适应Name和OwnerId,但是SaveChangesSync仍然失败

我查看了这个线程,但已经实现了这些更正:

ApplicationRoleStore.cs

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using MyApp.Models.Identity.Context;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace MyApp.Models.Identity
{
    public class ApplicationRoleStore : RoleStore<ApplicationRole, string, ApplicationUserRole>
    {
        private EntityStore<ApplicationRole> _roleStore;

        public ApplicationRoleStore(ApplicationDbContext context)
            : base(context)
        {
            _roleStore = new EntityStore<ApplicationRole>(context);
        }



        public IQueryable<ApplicationRole> GetStandardRoles()
        {
            var roles = Roles.AsNoTracking().Where(x => x.IsAdminRole == false && x.BaseRoleId == "");
            return (roles);
        }

        public IQueryable<ApplicationRole> GetTenantRoles(string ownerId)
        {
            var roles = Roles.AsNoTracking().Where(x => x.OwnerId == ownerId);
            return (roles);
        }

        public override async Task CreateAsync(ApplicationRole role)
        {
            if (role == null)
            {
                throw new ArgumentNullException("role");
            }

            if (String.IsNullOrEmpty(role.Id))
            {
                role.Id = Guid.NewGuid().ToString().ToLower();
            }

            _roleStore.Create(role);

            try
            {
                await Context.SaveChangesAsync().WithCurrentCulture();
            }
            catch (DbEntityValidationException e)
            {
                EntityValidationErrors.DisplayErrors(e);
                throw;
            }
        }
    }
}
使用Microsoft.AspNet.Identity;
使用Microsoft.AspNet.Identity.EntityFramework;
使用MyApp.Models.Identity.Context;
使用制度;
使用System.Collections.Generic;
使用System.Data.Entity;
使用System.Data.Entity.Validation;
使用System.Linq;
使用System.Threading.Tasks;
使用System.Web;
命名空间MyApp.Models.Identity
{
公共类应用程序RoleStore:RoleStore
{
私人实体商店;
公共应用程序角色存储(ApplicationDbContext上下文)
:基本(上下文)
{
_roleStore=新实体存储(上下文);
}
公共IQueryable GetStandardRoles()
{
var roles=roles.AsNoTracking()。其中(x=>x.IsAdminRole==false&&x.BaseRoleId==“”);
返回(角色);
}
公共IQueryable GetTenantRoles(字符串所有者ID)
{
var roles=roles.AsNoTracking(),其中(x=>x.OwnerId==OwnerId);
返回(角色);
}
公共重写异步任务CreateAsync(ApplicationRole角色)
{
如果(角色==null)
{
抛出新的ArgumentNullException(“角色”);
}
if(String.IsNullOrEmpty(role.Id))
{
role.Id=Guid.NewGuid().ToString().ToLower();
}
_roleStore.Create(角色);
尝试
{
wait Context.saveChangesSync().WithCurrentCulture();
}
捕获(DbEntityValidationException e)
{
EntityValidationErrors.DisplayErrors(e);
投掷;
}
}
}
}
ApplicationRoleValidator.cs

using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Resources;
using System.Threading.Tasks;
using System.Web;

namespace MyApp.Models.Identity
{
    public class ApplicationRoleValidator : RoleValidator<ApplicationRole, string>
    {
        public ApplicationRoleValidator(ApplicationRoleManager manager) : base(manager)
        {
            Manager = manager;
        }

        private ApplicationRoleManager Manager { get; set; }

        public override async Task<IdentityResult> ValidateAsync(ApplicationRole item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            var errors = new List<string>();
            await ValidateRoleName(item, errors).WithCurrentCulture();
            if (errors.Count > 0)
            {
                return IdentityResult.Failed(errors.ToArray());
            }
            return IdentityResult.Success;
        }

        private async Task ValidateRoleName(ApplicationRole role, List<string> errors)
        {
            if (string.IsNullOrWhiteSpace(role.Name))
            {
                errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PropertyTooShort, "Name"));
            }
            else
            {
                var owner = Manager.FindByNameAndOwner(role.Name, role.OwnerId);
                if (owner != null && !EqualityComparer<string>.Default.Equals(owner.Id, role.Id))
                {
                    errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.DuplicateName, role.Name));
                }
            }
        }
    }
}
使用Microsoft.AspNet.Identity;
使用制度;
使用System.Collections.Generic;
利用制度全球化;
使用System.Linq;
利用系统资源;
使用System.Threading.Tasks;
使用System.Web;
命名空间MyApp.Models.Identity
{
公共类应用程序RoleValidator:RoleValidator
{
公共应用程序角色管理器(ApplicationRoleManager):基本(manager)
{
经理=经理;
}
专用应用程序角色管理器管理器{get;set;}
公共覆盖异步任务ValidateAsync(ApplicationRole项)
{
如果(项==null)
{
抛出新的异常(“项”);
}
var errors=新列表();
等待ValidateRoleName(项,错误)。WithCurrentCulture();
如果(errors.Count>0)
{
返回IdentityResult.Failed(errors.ToArray());
}
返回IdentityResult.Success;
}
专用异步任务ValidateRoleName(ApplicationRole角色,列出错误)
{
if(string.IsNullOrWhiteSpace(role.Name))
{
errors.Add(String.Format(CultureInfo.currentcurity,Resources.PropertyTooShort,“Name”);
}
其他的
{
var owner=Manager.FindByNameAndOwner(role.Name,role.OwnerId);
if(owner!=null&!EqualityComparer.Default.Equals(owner.Id,role.Id))
{
添加(String.Format(CultureInfo.CurrentCulture,Resources.DuplicateName,role.Name));
}
}
}
}
}
ApplicationRole.cs

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations.Schema;

namespace MyApp.Models.Identity
{
    public class ApplicationRole : IdentityRole<string, ApplicationUserRole>
    {
        public ApplicationRole() : base()
        {
        }

        public ApplicationRole(string name) : this()
        {
            base.Name = name;
        }

        public ApplicationRole(string name, string ownerId) : this(name)
        {
            OwnerId = ownerId;
        }

        public ApplicationRole(string name, string description, string ownerId) : this(name, "", description, ownerId)
        {
        }

        public ApplicationRole(string name, string addrv, string description, string ownerId, string baseRoleId = "") : this(name, ownerId)
        {
            Abbrv = addrv;
            Description = description;
            BaseRoleId = baseRoleId;
        }

        public string Abbrv { get; set; }
        public string Description { get; set; }

        public int Order { get; set; } = 0;
        public bool IsAdminRole { get; set; } = false;

        public string OwnerId { get; set; }
        [ForeignKey("OwnerId")]
        public virtual ApplicationUser Owner { get; set; }

        public string BaseRoleId { get; set; }
        [ForeignKey("BaseRoleId")]
        public virtual ApplicationRole BaseRole { get; set; }

    }
}
使用Microsoft.AspNet.Identity;
使用Microsoft.AspNet.Identity.EntityFramework;
使用System.Threading.Tasks;
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用System.Web;
使用System.ComponentModel.DataAnnotations.Schema;
命名空间MyApp.Models.Identity
{
公共类应用程序角色:IdentityRole
{
公共应用程序角色():base()
{
}
公共应用程序角色(字符串名称):this()
{
base.Name=名称;
}
公共应用程序角色(字符串名称,字符串所有者ID):此(名称)
{
OwnerId=OwnerId;
}
公共应用程序角色(字符串名称、字符串描述、字符串所有者ID):此(名称、“、描述、所有者ID)
{
}
公共应用程序角色(字符串名称、字符串地址、字符串描述、字符串所有者ID、字符串baseRoleId=“”):此(名称、所有者ID)
{
Abbrv=addrv;
描述=描述;
BaseRoleId=BaseRoleId;
}
公共字符串Abbrv{get;set;}
公共字符串说明{get;set;}
公共整数顺序{get;set;}=0;
public bool isadmin role{get;set;}=false;
公共字符串所有者ID{get;set;}
[外键(“所有者ID”)]
公共虚拟应用程序用户所有者{get;set;}
公共字符串BaseRoleId{get;set;}
[外键(“BaseRoleId”)]
公共虚拟应用程序角色BaseRole{get;set;}
}
}
ApplicationDbContext.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using MyApp.Models.Identity;
using System.Threading.Tasks;
using System.Data.Entity;
using System.Security.Claims;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Infrastructure.Annotations;

namespace MyApp.Models.Identity.Context
{
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>
    {
        public ApplicationDbContext()
            : base("DefaultConnection")
        {
            base.Configuration.ProxyCreationEnabled = false;
        }

        static ApplicationDbContext()
        {
            // Set the database intializer which is run once during application start
            // This seeds the database with admin user credentials and admin role
            //Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
        }

        public static ApplicationDbContext Create()
        {
            ApplicationDbContext context = new ApplicationDbContext();
            context.Database.Initialize(true);
            return context;
        }

        //public virtual DbSet<ApplicationUser> Users { get; set; }
        //public virtual DbSet<ApplicationRole> Roles { get; set; }
        public virtual DbSet<UserDetail> UserDetails { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //modelBuilder.Entity<ApplicationUser>().HasMany<ApplicationUserRole>((ApplicationUser u) => u.Roles);

            modelBuilder.Entity<ApplicationUser>()
                          .ToTable("AspNetUsers");

            var role = modelBuilder.Entity<ApplicationRole>()
                          .ToTable("AspNetRoles");
            role.Property(r => r.Name)
                .IsRequired()
                .HasMaxLength(256)
                .HasColumnAnnotation("Index", new IndexAnnotation(
                    new IndexAttribute("RoleNameIndex", 1)
                    { IsUnique = true }));

            role.Property(r => r.OwnerId)
                .IsRequired()
                .HasMaxLength(128)
                .HasColumnAnnotation("Index", new IndexAnnotation(
                    new IndexAttribute("RoleNameIndex", 2)
                    { IsUnique = true }));

            modelBuilder.Entity<ApplicationUserRole>().HasKey((ApplicationUserRole r) =>
                new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("AspNetUserRoles");
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Web;
使用Microsoft.AspNet.Identity;
使用Microsoft.AspNet.Identity.EntityFramework;
使用MyApp.Models.Identity;
使用System.Threading.Tasks;
使用System.Data.Entity;
使用System.Security.Claims;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Data.Entity.Infrastructure.Annotations;
命名空间MyApp.Models.Identity.Context
{
公共类应用程序
    protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
    {
        var res =  base.ValidateEntity(entityEntry, items);
        //hack to convince EF that AspNetRole.Name does not need to be unique
        if (!res.IsValid
            && entityEntry.Entity is ApplicationRole
            && entityEntry.State == EntityState.Added
            && res.ValidationErrors.Count == 1
            && res.ValidationErrors.First().PropertyName == "Role")
        {
            return new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
        }

        return res;

    }