【问题标题】:DotNet Core 2 Seed User and RolesDotNet Core 2 种子用户和角色
【发布时间】:2018-08-10 00:57:41
【问题描述】:

使用 VS2017 内置的模板,用于带有身份验证的 Core 2 MVC。尝试使用用户和角色为数据库播种。角色运作良好,他们播种。用户总是返回一个错误说“不能为空”,我认为这是因为初始化函数末尾的这一行实际上找不到用户

await _userManager.AddToRoleAsync(await _userManager.FindByNameAsync(user), "Administrator");

我使用这篇文章来构建它: https://gist.github.com/mombrea/9a49716841254ab1d2dabd49144ec092

注意 - 这篇文章是针对 Core 1.0 的,而我正在使用 Core 2.0,这可能就是我遇到问题的原因。

如前所述,我可以播种角色,但用户不会自己创建。一旦我弄清楚这一点,我将尝试多个用户,我已经进行了创建多个角色的测试。

这里是初始化类

//Taken from :
    //https://gist.github.com/mombrea/9a49716841254ab1d2dabd49144ec092
    public interface IdentityDBIitializer
    {
        void Initialize();
    }

    public class LatestUserDBInitializer : IdentityDBIitializer
    {
        private readonly ApplicationDbContext _context;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;

        public LatestUserDBInitializer(
            ApplicationDbContext context,
            UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager)
        {
            _context = context;
            _userManager = userManager;
            _roleManager = roleManager;
        }

        //This example just creates an Administrator role and one Admin users
        public async void Initialize()
        {
            //create database schema if none exists
            _context.Database.EnsureCreated();

            //If there is already an Administrator role, abort
            //if (_context.Roles.Any(r => r.Name == "Administrator")) return;

            //Create the Administartor Role
            //await _roleManager.CreateAsync(new IdentityRole("Administrator"));

            //Create the default Admin account and apply the Administrator role
            string user = "me@myemail.com";
            string password = "z0mgchangethis";
            await _userManager.CreateAsync(new ApplicationUser { UserName = user, Email = user, EmailConfirmed = true }, password);
            await _userManager.AddToRoleAsync(await _userManager.FindByNameAsync(user), "Administrator");
        }
    }

这是我的启动:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<POSContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("UKFest2018Context")));

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("UKFestIdentityContext")));

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();


            // Add Database Initializer
            services.AddScoped<IdentityDBIitializer, LatestUserDBInitializer>();

            // Add application services.
            services.AddTransient<IEmailSender, EmailSender>();

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IdentityDBIitializer dBInitializer)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            //Seeds Identity DB
            dBInitializer.Initialize();

            //UserRoleInitializer.InitializeUsersAndRoles(app.ApplicationServices);

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

【问题讨论】:

  • ApplicationUser 中的一个字段不应为空,因此Cannot be NULL 可能需要查看哪个字段是必需的。
  • 试试这个密码,P@ssw0rd! 或者你可以在你的启动中设置自定义用户选项来获得你想要的任何类型的密码。

标签: .net-core asp.net-core-mvc asp.net-core-2.0


【解决方案1】:

对于您的问题,是因为您的密码无效导致创建用户失败。然后,await _userManager.FindByNameAsync(user) 将返回 null 而不是预期的用户。

您可以尝试使用 1qaz@WSX 之类的密码。

您可以参考enter link description here 查找默认要求。

【讨论】:

  • 这让用户创建,现在我收到一条错误消息:
  • 这个错误:System.ObjectDisposedException: 'Cannot access a disposed object.',这是在 githib 链接中引用的,所以我要去那里尝试一些解决方案
【解决方案2】:

哇,我在开发 .NET Core 2 Beta 时遇到同样的问题...

这可能意味着凭据不符合您的配置。或者,就我而言,我必须通过 IServiceProvider 获取 dbcontext 和管理器。

您可以在 Configure(...) 的末尾执行此操作

// Data seeding
            await Data.DataSeeder.SeedDatabase(app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope());

有一个数据播种器类,它使用 IServiceScope 来连接依赖项,噗

public class DataSeeder
    {
        public static async Task SeedDatabase(IServiceScope scope)
        {
            try
            {
                CounterDbContext context = scope.ServiceProvider.GetService<CounterDbContext>();

                CustoUserManager userManager = scope.ServiceProvider.GetRequiredService<CustoUserManager>();
                CustoRoleManager roleManager = scope.ServiceProvider.GetRequiredService<CustoRoleManager>();

                // SEED USER CODE HERE
                // SEED USER CODE HERE
                // SEED USER CODE HERE
                // SEED USER CODE HERE


                if (!context.CurrencyTypes.Any()) {
                        string[,] currencyTypes = new string[,] {
                            { "Crypto", "CRYPTO" },
                            { "Fiat Money", "FIAT" }
                        };

                        for (int i = 0; i < currencyTypes.GetLength(0); i++)
                        {
                            CurrencyType cType = new CurrencyType()
                            {
                                Name = currencyTypes[i, 0],
                                TypeShortForm = currencyTypes[i, 1],
                            };

                            context.CurrencyTypes.Add(cType);
                        }

                        context.SaveChanges(firstUser.Id);
                    }
}
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }

这可能会很乱……上面是播种班吧?以下是您为用户执行此操作的方法。

#if DEBUG
                string[] CreateUsers = { "nixholas"};
                string[] CreateNames = { "Nicholas" };
                string[] CreateEmails = { "xxx@xxxx.co" };
                string defaultPassword = "P@ssw0rd";

                // Seed the roles first
                // https://stackoverflow.com/questions/34343599/how-to-seed-users-and-roles-with-code-first-migration-using-identity-asp-net-mvc
                if (!roleManager.Roles.Any())
                {
                    foreach (UserRoleType role in Enum.GetValues(typeof(UserRoleType)))
                    {
                        var newRole = new Role();
                        newRole.Name = role.ToString();
                        await roleManager.CreateAsync(newRole);
                    }
                }

                if (await userManager.FindByEmailAsync(CreateEmails[0]) == null)
                {
                    for (int i = 0; i < CreateUsers.Length; i++)
                    {
                        User user = new User
                        {
                            Email = CreateEmails[i],
                            UserName = CreateUsers[i],
                            Name = CreateNames[i]
                        };

                        await userManager.CreateAsync(user, defaultPassword);

                        // Setup
                        await userManager.UpdateSecurityStampAsync(user);
                        user.NormalizedUserName = user.UserName;
                        user.NormalizedEmail = user.Email;
                        await userManager.UpdateNormalizedUserNameAsync(user);
                        await userManager.UpdateNormalizedEmailAsync(user);
                        await userManager.UpdateAsync(user);

                        // Email Automated Setup
                        var token = await userManager.GenerateEmailConfirmationTokenAsync(user);
                        await userManager.ConfirmEmailAsync(user, token);

                        await userManager.AddToRoleAsync(user, "Owner");
                    }
                }

【讨论】:

  • 谢谢@nicholas。我要试试这个,这个解决方案看起来比我做的要优雅一点。我仍在努力解决依赖注入和 iserviceproviders 的问题,我只是一名中级开发人员。我的解决方案有效,但对我来说感觉“混乱”。
猜你喜欢
  • 2018-02-28
  • 1970-01-01
  • 2013-10-17
  • 2015-06-14
  • 2016-10-03
  • 2020-09-13
  • 2020-06-07
  • 1970-01-01
  • 2020-02-25
相关资源
最近更新 更多