webentwicklung-frage-antwort-db.com.de

ASP.NET Core 2.2 IdentityUser erstellen

Neu bei ASP.Net Core. Mit Identity ein asp.net core 2.2-Projekt erstellen (und Benutzer festlegen lassen).

Ich kann keine Dokumentation dazu finden.

Ich konnte den Code zum Erstellen von Identitätsrollen finden (trotzdem kompiliert, bin noch nicht dort angelangt, wo ich ihn ausführen kann:

  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));
        }
     }
  }

Jetzt muss ich einige Benutzer erstellen. Aber das mit der komischen Microsoft-Syntax kann ich nicht finden (google seit 2 Tagen).

Folgendes funktioniert nicht :

   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");
  }

Der Fehler, den ich sehe, ist:

Argument1: Konvertierung von "Microsoft.AspNetCore.Identity.IdentityUser" nach "ApplicationDbContext" nicht möglich

Bedeutet das? Offensichtlich habe ich nicht den richtigen UserManager. Aber, wie bekomme ich den richtigen der einen Benutzer als ersten Parameter und eine Zeichenfolge (Passwort) als zweiten verwendet?

Darüber hinaus enthalten die Beispiele, die in Google-Suchen angezeigt werden, einApplicationUser-Objekt, das ich nicht habe (und nicht benötige?). In den Beispielen nicht definiert, wie ich es bekomme.

Owen

OK. Ich habe einen früheren Syntaxfehler, aber jetzt erhalte ich einen Laufzeitfehler:

NullReferenceException: Der Objektverweis wurde nicht auf eine Instanz eines Objekts festgelegt. beim Aufruf von CreateAsync. Hier ist der neue 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");
}

Sehen Sie sich an, welche anderen Parameter der create userManager hat und wie Sie diese vom serviceProvider abrufen können.

- Owen

Fand heraus, wie es geht. Der Schlüssel bestand darin, den richtigen Serviceprovider zu finden, um und die richtige Syntax zum Erstellen des userManagers zu übergeben. Die anderen Antworten, die ich über Google gefunden habe, alle ersetzen Sie die IdentityUser durch ihre eigene ApplicationUser, die das Wasser trübte. Hier ist die Arbeitsfunktion (hoffe, das hilft jemandem):

  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");
  }
3
Owen

Ihr Hauptproblem scheint die Abhängigkeitsinjektion zu sein. Schauen Sie unter diesem Link nach weiteren Informationen. Solange Sie Ihre DbContext und UserManager auf die richtige Weise injizieren, sollte der Rest des Codes in Ordnung sein. 

Hier ist ein Beispiel. Sie können einen separaten Dienst für das Seeding einrichten, um sicherzustellen, dass Sie Ihren Code vom Rest abkoppeln. 

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);
        }
    }

}

Sie müssen diese Klasse dann als Bereich hinzufügen (da Ihre DbContext Bereich ist), indem Sie services.AddScoped<UserSeeder>() in Ihrem Startup verwenden. Sie können jetzt einfach Ihre UserSeeder in einen beliebigen Dienst (mit Ausnahme von Singletons) einfügen und Ihre UserSeeder-Funktion aufrufen. Sie können beispielsweise UserSeeder in den Home-Controller einfügen und diesen Index-Vorgang aufrufen. Auf diese Weise wird das Säen zunächst überprüft und hinzugefügt. Dies funktioniert jedoch nur, WENN Sie zuerst zur Startseite gehen. Alternativ können Sie eine solche Middleware in Ihrer Startup-Klasse einrichten:

app.Use(async (context, next) => {
    await context.RequestServices.GetService<UserSeeder>().SeedAsync();
    await next();
});

Beachten Sie, dass Sie auf beide Arten die Datenbank jedes Mal aufrufen. Sie können planen, wo Sie es platzieren möchten. Sie können auch sicherstellen, dass dies nur einmal mit Hilfe eines Boolean aufgerufen wird (dies könnte in einem Singleton sein). Beachten Sie jedoch, dass dies nur beim Start der Anwendung ausgeführt werden kann. 

3

So sende ich meinen Admin-Benutzer (gelernt aus EF Core in Action book):

Dies ist die User-Klasse:

public class User : IdentityUser<long>
{
    //add your extra properties and relations
}

Der long-Typ gibt den Primärschlüsseltyp an. Wenn Sie die Standardklasse IdentityUser verwenden, wird es eine Zeichenfolge sein (uniqueidentifier in SQL).

Dies ist die Role-Klasse:

public class Role : IdentityRole<long>
{
    public static string Admin = "Admin";
}

Es kann leer sein, ich verwende statische Zeichenfolgen, um magische Zeichenfolgen in meinem Code zu vermeiden.

Dies ist die DbContext:

public class ApplicationDbContext : IdentityDbContext<User, Role, long>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    { }

    //your DbSets and configurations
    //...
}

Wenn Sie Identity verwenden möchten, müssen Sie IdentityDbContext verwenden und Ihre benutzerdefinierte Klasse User und Role sowie den Typ des verwendeten Primärschlüssels angeben.

Dieser Code fügt dem Programm Identität hinzu:

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();

    //...
}

Dies ist eine Erweiterungsmethode für Seed-Daten:

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;
    }
}

Und schließlich verwenden Sie es in Ihrem Program.cs:

CreateWebHostBuilder(args)
    .Build()
    .SeedAdminUser()
    .Run();
0
Sasan