Nouveauté ASP.Net Core. Il faut créer un projet asp.net core 2.2 avec Identity (et créer des utilisateurs).
Je ne trouve aucune documentation sur la manière de procéder.
J'ai pu trouver le code pour créer des rôles d'identité (compile de toute façon, je ne suis pas encore arrivé à l'endroit où je peux l'exécuter:
private static async Task CreateUserTypes(ApplicationDbContext authContext, IServiceProvider serviceProvider)
{
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roleNames = { "Administrator", "Data Manager", "Interviewer", "Respondent" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
}
Maintenant, je dois créer des utilisateurs. Mais le avec la syntaxe Microsoft étrange pour faire que je ne trouve pas (été googler pendant 2 jours).
Voici ce qui fonctionne not:
private static async Task CreateRootUser(Models.CensORContext context, ApplicationDbContext authContext, IServiceProvider serviceProvider)
{
//Create the root ADMIN user for all things admin.
UserManager<ApplicationDbContext> userManager = serviceProvider.GetRequiredService<UserManager<ApplicationDbContext>>();
IdentityUser user = new IdentityUser()
{
UserName = "[email protected]",
Email = "[email protected]"
};
var NewAdmin = await userManager.CreateAsync(user, "password");
}
L'erreur que je vois est:
Argument1: impossible de convertir 'Microsoft.AspNetCore.Identity.IdentityUser' en 'ApplicationDbContext'
Cela signifie t-il? De toute évidence, je n'ai pas le bon userManager. Mais, comment puis-je obtenir le bon qui prend un utilisateur en tant que premier paramètre et une chaîne (mot de passe) pour le deuxième?
De plus, les exemples qui apparaissent dans les recherches Google ont un objet ApplicationUser
que je n’ai pas (et dont je n’ai pas besoin?). Non défini dans les exemples pour savoir comment je l'obtiens.
Owen
D'ACCORD. Vous avez une erreur de syntaxe passée, mais maintenant, je reçois une erreur d'exécution:
NullReferenceException: La référence à un objet n'est pas définie sur une instance d'un objet. sur l'appel de CreateAsync. Voici le nouveau code:
private static async Task CreateRootUser(Models.CensORContext context, ApplicationDbContext authContext, IServiceProvider serviceProvider)
{
//Create the root ADMIN user for all things admin.
var userStore = new UserStore<IdentityUser>(authContext);
UserManager<IdentityUser> userManager = new UserManager<IdentityUser>(userStore, null, null, null, null, null, null, serviceProvider, null);
// = serviceProvider.GetRequiredService<UserManager<ApplicationDbContext>>();
IdentityUser user = new IdentityUser()
{
UserName = "[email protected]",
Email = "[email protected]"
};
var result = await userManager.CreateAsync(user, "password");
}
Vous allez examiner quels sont les autres paramètres du userManager de create et comment les obtenir auprès de serviceProvider?
--Owen
Compris comment le faire. La clé était de trouver le bon fournisseur de services pour transmettre et la bonne syntaxe pour la création de userManager. Les autres réponses que j’ai trouvées dans Google tout remplacent la IdentityUser
par leur propre ApplicationUser
qui brouillait l’eau. Voici la fonction de travail (espérons que cela aide quelqu'un):
private static async Task CreateRootUser(Models.CensORContext context, ApplicationDbContext authContext, IServiceProvider serviceProvider)
{
//Create the root ADMIN user for all things admin.
var userStore = new UserStore<IdentityUser>(authContext);
UserManager<IdentityUser> userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
//new UserManager<IdentityUser>(userStore, null, null, null, null, null, null, serviceProvider, null);
// = serviceProvider.GetRequiredService<UserManager<ApplicationDbContext>>();
IdentityUser user = new IdentityUser()
{
UserName = "[email protected]",
Email = "[email protected]"
};
var result = await userManager.CreateAsync(user, "password");
result = await userManager.AddToRoleAsync(user, "Administrator");
}
Votre problème principal semble être l'injection de dépendance. Regardez ce lien pour plus d'informations. Tant que vous injectez votre DbContext
et UserManager
de la bonne manière et que le reste du code devrait bien se passer.
Voici un exemple. Vous pouvez configurer un service séparé pour la distribution afin de vous assurer que votre code est découplé du reste.
public class UserSeeder
{
private readonly UserManager<IdentityUser> userManager;
private readonly ApplicationDbContext context;
public UserSeeder(UserManager<IdentityUser> userManager, ApplicationDbContext context)
{
this.userManager = userManager;
this.context = context;
}
public async Task `()
{
string username = "[email protected]";
var users = context.Users;
if (!context.Users.Any(u => u.UserName == username))
{
var done = await userManager.CreateAsync(new IdentityUser
{
UserName = username,
Email = username
}, username);
}
}
}
Vous devez ensuite ajouter cette classe en tant que portée (puisque votre DbContext
est portée) en utilisant services.AddScoped<UserSeeder>()
dans votre démarrage. Vous pouvez maintenant simplement injecter votre UserSeeder
dans n’importe quel service (sauf les singletons) et appeler votre fonction UserSeeder
. Par exemple, vous pouvez injecter UserSeeder
dans le contrôleur d'origine et appeler l'action index. De cette façon, le semis est vérifié et ajouté initialement. Cependant, cela ne fonctionnera que si vous allez d'abord sur la page d'accueil. Alternativement, vous pouvez configurer un middleware comme celui-ci dans votre classe de démarrage:
app.Use(async (context, next) => {
await context.RequestServices.GetService<UserSeeder>().SeedAsync();
await next();
});
Notez que ces deux manières, vous appelez la base de données à chaque fois. Vous pouvez planifier où le placer. Vous pouvez également vous assurer que ce n'est appelé qu'une seule fois à l'aide d'un booléen (éventuellement en singleton). Mais notez que cela ne fonctionnerait qu'au démarrage de l'application.
Voici comment je sème mon utilisateur Admin (appris de EF Core in Action book):
C'est la classe User
:
public class User : IdentityUser<long>
{
//add your extra properties and relations
}
Le type long
spécifie le type de clé primaire. Si vous utilisez la classe IdentityUser
par défaut, il s'agira d'une chaîne (identifiant unique en SQL).
C'est la classe Role
:
public class Role : IdentityRole<long>
{
public static string Admin = "Admin";
}
Il peut être vide, j'utilise des chaînes statiques pour éviter les chaînes magiques dans mon code.
C'est la DbContext
:
public class ApplicationDbContext : IdentityDbContext<User, Role, long>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
//your DbSets and configurations
//...
}
Si vous envisagez d'utiliser Identity, vous devez utiliser IdentityDbContext
et spécifier votre classe User
et Role
personnalisée et le type de clé primaire que vous utilisez.
Ce code ajoute une identité au programme:
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddIdentity<User, Role>(options =>
{
//you can configure your password and user policy here
//for example:
options.Password.RequireDigit = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//...
}
C'est une méthode d'extension pour créer des données:
public static class SeedData
{
public static IWebHost SeedAdminUser(this IWebHost webHost)
{
using (var scope = webHost.Services.CreateScope())
{
try
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
context.Database.EnsureCreated();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<Role>>();
if (!userManager.Users.Any(u => u.Email == "[email protected]"))
{
roleManager.CreateAsync(new Role()
{
Name = Role.Admin
})
.Wait();
userManager.CreateAsync(new User
{
UserName = "Admin",
Email = "[email protected]"
}, "secret")
.Wait();
userManager.AddToRoleAsync(userManager.FindByEmailAsync("[email protected]").Result, Role.Admin).Wait();
}
}
catch (Exception ex)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding user.");
//throw;
}
}
return webHost;
}
}
Et enfin, utilisez-le dans votre Program.cs
:
CreateWebHostBuilder(args)
.Build()
.SeedAdminUser()
.Run();