首页 文章

asp.net核心2.2创建IdentityUser

提问于
浏览
1

全新的ASP.Net Core . 必须通过MONDAY MORNING创建一个带有Identity的asp.net核心2.2项目(并有用户播种)!

我找不到任何关于如何准确执行此操作的文档 .

我能够找到创建身份角色的代码(无论如何编译,还没有到达我可以运行它的地方:

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

现在,我需要创建一些用户 . 但超级令人沮丧的 - 超级难度 - 愚蠢 - 微软 - 语法,我无法找到(谷歌搜索2天) .

这是不起作用的:

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 = "admin@admin.admin",
        Email = "admin@admin.admin"
     };

     var NewAdmin = await userManager.CreateAsync(user, "password");
  }

我看到的错误是:

Argument1:无法从'Microsoft.AspNetCore.Identity.IdentityUser'转换为'ApplicationDbContext'

这是什么意思?显然,我没有合适的userManager . 但是,我如何获得正确的第一个参数和第二个字符串(密码)?

哦,Google搜索中出现的示例有一个我没有的 ApplicationUser 对象(并且不需要?) . 我没有在示例中定义如何获得它 .

请帮忙!

欧文

好 . 得到过去的语法错误,但现在我收到运行时错误:

NullReferenceException:未将对象引用设置为对象的实例 . 在调用CreateAsync时 . 这是新代码:

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 = "admin@admin.admin",
        Email = "admin@admin.admin"
     };

     var result = await userManager.CreateAsync(user, "password");
}

要查看create userManager的其他参数以及如何从serviceProvider获取它们?

--Owen

弄清楚如何做到这一点 . 关键是找到正确的serviceprovider来传递和创建userManager的正确语法 . 我通过谷歌找到的其他答案全部用他们自己的ApplicationUser取代了IdentityUser,这会使水变得混乱 . 这是工作功能(希望这有助于某人):

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 = "admin@admin.admin",
        Email = "admin@admin.admin"
     };

     var result = await userManager.CreateAsync(user, "password");
     result = await userManager.AddToRoleAsync(user, "Administrator");
  }

2 回答

  • 0

    以下是我为管理员用户提供的方法(从 EF Core in Action 书中学习):

    这是 User 类:

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

    long 类型指定主键类型 . 如果使用默认的 IdentityUser 类,它将是字符串(SQL中的uniqueidentifier) .

    这是 Role 类:

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

    它可以是空的,我使用静态字符串来避免代码中的魔术字符串 .

    这是 DbContext

    public class ApplicationDbContext : IdentityDbContext<User, Role, long>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        { }
    
        //your DbSets and configurations
        //...
    }
    

    如果您要使用Identity,则需要使用 IdentityDbContext 并指定自定义 UserRole 类以及您正在使用的主键类型 .

    此代码将Identity添加到程序中:

    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();
    
        //...
    }
    

    这是种子数据的扩展方法:

    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 == "admin@domain.com"))
                    {
                        roleManager.CreateAsync(new Role()
                        {
                            Name = Role.Admin
                        })
                        .Wait();
    
                        userManager.CreateAsync(new User
                        {
                            UserName = "Admin",
                            Email = "admin@domain.com"
                        }, "secret")
                        .Wait();
    
                        userManager.AddToRoleAsync(userManager.FindByEmailAsync("admin@domain.com").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;
        }
    }
    

    最后在你的_64676中使用它:

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

    你的主要问题似乎是依赖注入 . 有关更多信息,请查看this link . 只要您以正确的方式注入 DbContextUserManager ,其余代码就可以了 .

    这是一个例子 . 您可以为播种设置单独的服务,以确保您将代码与其余代码分离 .

    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 = "admin@admin.admin";
            var users = context.Users;
            if (!context.Users.Any(u => u.UserName == username))
            {
                var done = await userManager.CreateAsync(new IdentityUser
                {
                    UserName = username,
                    Email = username
                }, username);
            }
        }
    
    }
    

    然后,您必须在启动时使用 services.AddScoped<UserSeeder>() 将此类添加为作用域(因为您的 DbContext 是作用域的) . 您现在可以在任何服务(单例除外)中简单地注入 UserSeeder 并调用 UserSeeder 函数 . 例如,您可以在家庭控制器中注入 UserSeeder 并将其称为索引操作 . 这样,最初检查并添加种子 . 但是,这只有在您首先访问主页时才有效 . 或者,您可以在启动类中设置这样的中间件:

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

    请注意,这两种方式,您每次都在调用数据库 . 您可以计划放置它的位置 . 您还可以确保仅在布尔值的帮助下调用此对象(可以是单例) . 但请注意,这只会在应用程序启动时运行 .

相关问题