Hi, I would like to customize IdentityDbContext with my own implemention but I got an error why ?
error message : Cannot use table 'AspNetRoleClaims' in schema '' for entity 'AspNetRoleClaims' since it is being used for another entity
public class MyIdentityDbContext : IdentityDbContext<MyUser>
{
public virtual DbSet<AspNetRoleClaims> AspNetRoleClaims { get; set; }
public virtual DbSet<AspNetRoles> AspNetRoles { get; set; }
public virtual DbSet<AspNetUserClaims> AspNetUserClaims { get; set; }
public virtual DbSet<AspNetUserLogins> AspNetUserLogins { get; set; }
public virtual DbSet<AspNetUserRoles> AspNetUserRoles { get; set; }
public virtual DbSet<AspNetUserTokens> AspNetUserTokens { get; set; }
public virtual DbSet<AspNetUsers> AspNetUsers { get; set; }
public MyIdentityDbContext(DbContextOptions<MyIdentityDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<AspNetRoleClaims>(entity =>
{
entity.HasIndex(e => e.RoleId)
.HasName("IX_AspNetRoleClaims_RoleId");
entity.Property(e => e.RoleId)
.IsRequired()
.HasMaxLength(450);
entity.HasOne(d => d.Role)
.WithMany(p => p.AspNetRoleClaims)
.HasForeignKey(d => d.RoleId);
});
modelBuilder.Entity<AspNetRoles>(entity =>
{
entity.HasIndex(e => e.NormalizedName)
.HasName("RoleNameIndex");
entity.Property(e => e.Id).HasMaxLength(450);
entity.Property(e => e.Name).HasMaxLength(256);
entity.Property(e => e.NormalizedName).HasMaxLength(256);
});
modelBuilder.Entity<AspNetUserClaims>(entity =>
{
entity.HasIndex(e => e.UserId)
.HasName("IX_AspNetUserClaims_UserId");
entity.Property(e => e.UserId)
.IsRequired()
.HasMaxLength(450);
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserClaims)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUserLogins>(entity =>
{
entity.HasKey(e => new { e.LoginProvider, e.ProviderKey })
.HasName("PK_AspNetUserLogins");
entity.HasIndex(e => e.UserId)
.HasName("IX_AspNetUserLogins_UserId");
entity.Property(e => e.LoginProvider).HasMaxLength(450);
entity.Property(e => e.ProviderKey).HasMaxLength(450);
entity.Property(e => e.UserId)
.IsRequired()
.HasMaxLength(450);
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserLogins)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUserRoles>(entity =>
{
entity.HasKey(e => new { e.UserId, e.RoleId })
.HasName("PK_AspNetUserRoles");
entity.HasIndex(e => e.RoleId)
.HasName("IX_AspNetUserRoles_RoleId");
entity.HasIndex(e => e.UserId)
.HasName("IX_AspNetUserRoles_UserId");
entity.Property(e => e.UserId).HasMaxLength(450);
entity.Property(e => e.RoleId).HasMaxLength(450);
entity.HasOne(d => d.Role)
.WithMany(p => p.AspNetUserRoles)
.HasForeignKey(d => d.RoleId);
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserRoles)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUserTokens>(entity =>
{
entity.HasKey(e => new { e.UserId, e.LoginProvider, e.Name })
.HasName("PK_AspNetUserTokens");
entity.Property(e => e.UserId).HasMaxLength(450);
entity.Property(e => e.LoginProvider).HasMaxLength(450);
entity.Property(e => e.Name).HasMaxLength(450);
});
modelBuilder.Entity<AspNetUsers>(entity =>
{
entity.HasIndex(e => e.NormalizedEmail)
.HasName("EmailIndex");
entity.HasIndex(e => e.NormalizedUserName)
.HasName("UserNameIndex")
.IsUnique();
entity.Property(e => e.Id).HasMaxLength(450);
entity.Property(e => e.Email).HasMaxLength(256);
entity.Property(e => e.NormalizedEmail).HasMaxLength(256);
entity.Property(e => e.NormalizedUserName)
.IsRequired()
.HasMaxLength(256);
entity.Property(e => e.UserName).HasMaxLength(256);
});
}
} public class MyUserStore : IUserStore<MyUser>, IUserPasswordStore<MyUser>, IUserLoginStore<MyUser>, IUserEmailStore<MyUser>,
IUserRoleStore<MyUser>, IUserClaimStore<MyUser>
{
private readonly IUserRepository<MyUser> _userRepository;
private readonly IRoleRepository<MyRole> _roleRepository;
public MyUserStore(IUserRepository<MyUser> userRepository, IRoleRepository<MyRole> roleRepository)
{
_userRepository = userRepository;
_roleRepository = roleRepository;
}
public async Task AddClaimsAsync(MyUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
{
await Task.Run(() =>
{
foreach (var claim in claims)
{
user.Claims.Add(new Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>
{
ClaimType = claim.Type,
ClaimValue = claim.Value,
UserId = user.Id
});
}
}
);
}
public Task AddLoginAsync(MyUser user, UserLoginInfo login, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task AddToRoleAsync(MyUser user, string roleName, CancellationToken cancellationToken)
{
await _roleRepository.AddToRoleAsync(user.Id, roleName);
}
public async Task<IdentityResult> CreateAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
return await _userRepository.CreateAsync(user);
}
public Task<IdentityResult> DeleteAsync(MyUser user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public void Dispose()
{
//throw new NotImplementedException();
}
public Task<MyUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<MyUser> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<MyUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<MyUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(normalizedUserName))
{
throw new ArgumentException("Null or empty argument: userName");
}
return await _userRepository.FindByNameAsync(normalizedUserName);
}
public async Task<IList<Claim>> GetClaimsAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Null or empty argument: user");
}
return await _userRepository.GetClaimsAsync(user.Id);
}
public async Task<string> GetEmailAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Null or empty argument: user");
}
return await Task.FromResult(user.Email);
//return await _userRepository.GetEmailAsync(user.Id);
}
public Task<bool> GetEmailConfirmedAsync(MyUser user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<IList<UserLoginInfo>> GetLoginsAsync(MyUser user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetNormalizedEmailAsync(MyUser user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetNormalizedUserNameAsync(MyUser user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<string> GetPasswordHashAsync(MyUser user, CancellationToken cancellationToken)
{
return await _userRepository.GetPasswordHashAsync(user);
}
public async Task<IList<string>> GetRolesAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Null or empty argument: user");
}
return await _userRepository.GetRolesAsync(user.Id);
}
public async Task<string> GetUserIdAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Null or empty argument: user");
}
return await Task.FromResult(user.Id);
}
public async Task<string> GetUserNameAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Null or empty argument: user");
}
return await Task.FromResult(user.UserName ?? user.NormalizedUserName);
}
public Task<IList<MyUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<IList<MyUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<bool> HasPasswordAsync(MyUser user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<bool> IsInRoleAsync(MyUser user, string roleName, CancellationToken cancellationToken)
{
//return await _userRepository.GetRolesAsync(user.Id);
return false;
}
public Task RemoveClaimsAsync(MyUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task RemoveFromRoleAsync(MyUser user, string roleName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task RemoveLoginAsync(MyUser user, string loginProvider, string providerKey, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task ReplaceClaimAsync(MyUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetEmailAsync(MyUser user, string email, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetEmailConfirmedAsync(MyUser user, bool confirmed, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task SetNormalizedEmailAsync(MyUser user, string normalizedEmail, CancellationToken cancellationToken)
{
await Task.Run(() => user.NormalizedEmail = normalizedEmail);
}
public async Task SetNormalizedUserNameAsync(MyUser user, string normalizedName, CancellationToken cancellationToken)
{
await Task.Run(() => user.NormalizedUserName = normalizedName);
}
public async Task SetPasswordHashAsync(MyUser user, string passwordHash, CancellationToken cancellationToken)
{
await Task.Run(() => user.PasswordHash = passwordHash);
}
public async Task SetUserNameAsync(MyUser user, string userName, CancellationToken cancellationToken)
{
await Task.Run(() => user.UserName = userName);
}
public async Task<IdentityResult> UpdateAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Null or empty argument: user");
}
return await _userRepository.UpdateAsync(user);
}
}public class MyRoleStore : IRoleStore<MyRole>
{
#region IRoleStore
private readonly IRoleRepository<MyRole> _roleRepository;
public MyRoleStore(IRoleRepository<MyRole> roleRepository)
{
_roleRepository = roleRepository;
}
/// <summary>
/// Create a new role
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IdentityResult> CreateAsync(MyRole role, CancellationToken cancellationToken)
{
if (role == null)
{
var error = new IdentityError { Code = "1", Description = "Role cannot be null" };
return IdentityResult.Failed(error);
}
await _roleRepository.CreateAsync(role);
return IdentityResult.Success;
}
/// <summary>
/// Delete a role
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IdentityResult> DeleteAsync(MyRole role, CancellationToken cancellationToken)
{
if (role == null)
{
var error = new IdentityError { Code = "1", Description = "Role cannot be null" };
return IdentityResult.Failed(error);
}
await _roleRepository.DeleteAsync(role.Id);
return IdentityResult.Success;
}
/// <summary>
/// Dispose service
/// </summary>
public void Dispose()
{
//throw new NotImplementedException();
}
/// <summary>
/// Find a role by id
/// </summary>
/// <param name="roleId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<MyRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
{
throw (new NotImplementedException());
}
/// <summary>
/// Find a role by name
/// </summary>
/// <param name="normalizedRoleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<MyRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
return await _roleRepository.FindByNameAsync(normalizedRoleName);
}
/// <summary>
/// Find a role by normalized role name
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<string> GetNormalizedRoleNameAsync(MyRole role, CancellationToken cancellationToken)
{
return Task.FromResult(role.Name.ToUpper());
}
/// <summary>
/// Get id of a role
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<string> GetRoleIdAsync(MyRole role, CancellationToken cancellationToken)
{
return Task.FromResult(role.Id.ToString());
}
/// <summary>
/// Get name of a role
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<string> GetRoleNameAsync(MyRole role, CancellationToken cancellationToken)
{
return Task.FromResult(role.Name);
}
/// <summary>
/// Set normalized name for a role
/// </summary>
/// <param name="role"></param>
/// <param name="normalizedName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task SetNormalizedRoleNameAsync(MyRole role, string normalizedName, CancellationToken cancellationToken)
{
await Task.Run(() => role.NormalizedName = normalizedName);
}
/// <summary>
/// Set name for a role
/// </summary>
/// <param name="role"></param>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task SetRoleNameAsync(MyRole role, string roleName, CancellationToken cancellationToken)
{
await Task.Run(() => role.Name = roleName);
}
/// <summary>
/// Update an existing role
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<IdentityResult> UpdateAsync(MyRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
#endregion
}public class MyUser : IdentityUser
{
}public class MyRole : IdentityRole
{
} // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(Configuration);
// Add framework services.
services.AddMvc();
services.AddDbContext<MyIdentityDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SecurityConnection"), sqlOptions => sqlOptions.MigrationsAssembly("MySample.WebApi.Core")));
services.AddIdentity<MyUser, MyRole>(cfg =>
{
// if we are accessing the /api and an unauthorized request is made
// do not redirect to the login page, but simply return "Unauthorized"
cfg.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = ctx =>
{
if (ctx.Request.Path.StartsWithSegments("/api"))
ctx.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
return Task.FromResult(0);
}
};
}).AddEntityFrameworkStores<MyIdentityDbContext>()
.AddDefaultTokenProviders();
services.AddScoped<IUserRepository<MyUser>, UserRepository>();
services.AddScoped<IRoleRepository<MyRole>, RoleRepository>();
services.AddScoped<IRoleStore<MyRole>, MyRoleStore>();
services.AddScoped<IUserStore<MyUser>, MyUserStore>();
}But I have an error at runtime:
The exception occurs in MyUserRepository : databaseContext.AspNetUsers.SingleOrDefault(u => u.UserName == normalizedUserName);
public async Task<MyUser> FindByNameAsync(string normalizedUserName)
{
return await Task.Run(() =>
{
var user = _databaseContext.AspNetUsers.SingleOrDefault(u => u.UserName == normalizedUserName);
How to use it correctly ?
Regards