Je migre une application ASP.NET Core 1.0 vers ASP.NET Core 2.0.
Dans ma startup, je configure deux identités:
services.AddIdentity<IdentityUser, IdentityRole>(configureIdentity)
.AddDefaultTokenProviders()
.AddUserStore<IdentityUserStore<IdentityUser>>()
.AddRoleStore<IdentityRoleStore<IdentityRole>>();
services.AddIdentity<Customer, CustomerRole>(configureIdentity)
.AddDefaultTokenProviders()
.AddErrorDescriber<CustomerIdentityErrorDescriber>()
.AddUserStore<CustomerStore<Customer>>()
.AddRoleStore<CustomerRoleStore<CustomerRole>>();
Cela fonctionnait bien dans ASP.NET Core 1.0 mais échouait avec l'erreur suivante: System.InvalidOperationException: "Le schéma existe déjà: Identity.Application" dans ASP.NET Core 2.0.
Dans ASP.NET Core 2.0, si je supprime l'un des appels à AddIdentity
, l'erreur disparaît. Comment migrer mon code pour pouvoir utiliser deux types d'utilisateur et de rôle d'identité différents dans mon application? Ou ai-je simplement commis une erreur fondamentale en comprenant le fonctionnement des choses lorsque j'ai écrit cela dans ASP.NET Core 1.0?
Après avoir examiné le code source ASP.NET Core sur github, une deuxième identité pourrait être ajoutée à l'aide de cette méthode d'extension:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;
namespace Whatever
{
public static class IdentityExtensions
{
public static IdentityBuilder AddSecondIdentity<TUser, TRole>(
this IServiceCollection services)
where TUser : class
where TRole : class
{
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();
services.TryAddScoped<RoleManager<TRole>, AspNetRoleManager<TRole>>();
return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
}
}
}
Merci beaucoup pour votre réponse, Keith. Cela m'a fait gagner beaucoup de temps!… Une petite amélioration: j'ai dû configurer certaines options (IdentityOptions) dans mon cas. Comme par exemple: Règles de complexité du mot de passe.
J'ai donc inclus l'enregistrement de l'action setupAction. (Microsoft procède de la même manière dans AddIdentity dans IdentityServiceCollectionExtension)
public static class IdentityExtensions
{
public static IdentityBuilder AddSecondIdentity<TUser, TRole>(
this IServiceCollection services, Action<IdentityOptions> setupAction)
where TUser : class
where TRole : class
{
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();
services.TryAddScoped<RoleManager<TRole>, AspNetRoleManager<TRole>>();
if (setupAction != null)
services.Configure(setupAction);
return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
}
}