-
-
Save mombrea/9a49716841254ab1d2dabd49144ec092 to your computer and use it in GitHub Desktop.
using Microsoft.AspNetCore.Identity; | |
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | |
using System.Linq; | |
namespace My.App.Data | |
{ | |
public class DbInitializer : IDbInitializer | |
{ | |
private readonly ApplicationDbContext _context; | |
private readonly UserManager<ApplicationUser> _userManager; | |
private readonly RoleManager<IdentityRole> _roleManager; | |
public DbInitializer( | |
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 = "[email protected]"; | |
string password = "z0mgchangethis"; | |
await _userManager.CreateAsync(new ApplicationUser { UserName = user, Email = user, EmailConfirmed = true}, password); | |
await _userManager.AddToRoleAsync(await _userManager.FindByNameAsync(user), "Administrator"); | |
} | |
} | |
} |
namespace My.App.Data | |
{ | |
public interface IDbInitializer | |
{ | |
void Initialize(); | |
} | |
} |
using Microsoft.AspNetCore.Builder; | |
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | |
using Microsoft.EntityFrameworkCore; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Logging; | |
using My.App.Data; | |
namespace My.App.Admin | |
{ | |
public class Startup | |
{ | |
public Startup(IHostingEnvironment env) | |
{ | |
var builder = new ConfigurationBuilder() | |
.SetBasePath(env.ContentRootPath) | |
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); | |
if (env.IsDevelopment()) | |
{ | |
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 | |
builder.AddUserSecrets<Startup>(); | |
} | |
builder.AddEnvironmentVariables(); | |
Configuration = builder.Build(); | |
} | |
public IConfigurationRoot Configuration { get; } | |
// This method gets called by the runtime. Use this method to add services to the container. | |
public void ConfigureServices(IServiceCollection services) | |
{ | |
// Add framework services. | |
services.AddDbContext<ApplicationDbContext>(options => | |
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); | |
services.AddIdentity<ApplicationUser, IdentityRole>() | |
.AddEntityFrameworkStores<ApplicationDbContext>() | |
.AddDefaultTokenProviders(); | |
services.AddMvc(); | |
// Add Database Initializer | |
services.AddScoped<IDbInitializer, DbInitializer>(); | |
// Add application services. | |
services.AddTransient<IEmailSender, AuthMessageSender>(); | |
services.AddTransient<ISmsSender, AuthMessageSender>(); | |
} | |
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IDbInitializer dbInitializer) | |
{ | |
loggerFactory.AddConsole(Configuration.GetSection("Logging")); | |
loggerFactory.AddDebug(); | |
if (env.IsDevelopment()) | |
{ | |
app.UseDeveloperExceptionPage(); | |
app.UseDatabaseErrorPage(); | |
// Browser Link is not compatible with Kestrel 1.1.0 | |
// For details on enabling Browser Link, see https://go.microsoft.com/fwlink/?linkid=840936 | |
// app.UseBrowserLink(); | |
} | |
else | |
{ | |
app.UseExceptionHandler("/Home/Error"); | |
} | |
app.UseStaticFiles(); | |
app.UseIdentity(); | |
//Generate EF Core Seed Data | |
dbInitializer.Initialize(); | |
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715 | |
app.UseMvc(routes => | |
{ | |
routes.MapRoute( | |
name: "default", | |
template: "{controller=Home}/{action=Index}/{id?}"); | |
}); | |
} | |
} | |
} |
@ych-szh You are amazing. Thank you! What exactly does using this scope achieve?
I was also having issues with System.ObjectDisposedException: 'Cannot access a disposed object.'
and eventually went with a new approach that uses an IWebHost
extension off of ASP.Net Core 2.x.
I get rid of System.ObjectDisposedException: 'Cannot access a disposed object.'
when I change this:
_context.Database.EnsureCreated();
await _roleManager.CreateAsync(new IdentityRole("Administrator"));
await _userManager.CreateAsync(new ApplicationUser { UserName = user, Email = user, EmailConfirmed = true}, password);
to this:
_context.Database.Migrate();
_roleManager.CreateAsync(new IdentityRole("Administrator")).GetAwaiter().GetResult();
_userManager.CreateAsync(new ApplicationUser { UserName = user, Email = user, EmailConfirmed = true }, password).GetAwaiter().GetResult();
In DoTNet Core 2.0 when I try and run this I get an error on the user creation that says "Value cannot be Null". I am guessing the last line of the initializer:
await _userManager.AddToRoleAsync(await _userManager.FindByNameAsync(user), "Administrator");
has a problem finding the user, but I cannot figure out why. Any ideas?
@daveinyyc can you post rest of your code?
It was because the password listed in this code is not complex enough @ibro, DotNet 2.0 adds some password complexity requirements obviously. Now I have fixed that and the user is creating, but i am getting the dispose error the other commentators mentioned. going to try the GetAwaiter().GetResult() statements like @Planche95 mentions in his comment
The example works if you change the interface to return type Task instead of type void.
namespace My.App.Data { public interface IDbInitializer { Task Initialize(); } }
Also use public async Task Initialize()
inside DbInitializer.
@grumson
Check this:
aspnet/Identity#1065