问题
I have a ASP.NET Core 1.0 Solution with 3 projects (Web, Console Application, DataAccessLayer). I use ASP.NET Core Identity and Entity Framework Core (SQL Server - Code First).
In my Console Application (Used for background tasks), I want to create users, but how I can have access to UserManager object in a Console Application (Or in a .NET Core Class Library) ?
In a controller class, it's easy with Dependency Injection :
public class AccountController : Controller {
private readonly UserManager<ApplicationUser> _userManager;
public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
}
//...
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
//...
}
How I can do the equivalent in a Console Core Application ?
回答1:
Thanks to Tseng's answer I ended up with this code. Just in case if someone would need:
public class Program
{
private interface IUserCreationService
{
Task CreateUser();
}
public static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddDbContext<ApplicationDbContext>(
options =>
{
options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=my-app-db;Trusted_Connection=True;MultipleActiveResultSets=true");
});
// Authentification
services.AddIdentity<ApplicationUser, IdentityRole>(opt =>
{
// Configure identity options
opt.Password.RequireDigit = false;
opt.Password.RequireLowercase = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequiredLength = 6;
opt.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddScoped<IUserCreationService, UserCreationService>();
// Build the IoC from the service collection
var provider = services.BuildServiceProvider();
var userService = provider.GetService<IUserCreationService>();
userService.CreateUser().GetAwaiter().GetResult();
Console.ReadKey();
}
private class UserCreationService : IUserCreationService
{
private readonly UserManager<ApplicationUser> userManager;
public UserCreationService(UserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public async Task CreateUser()
{
var user = new ApplicationUser { UserName = "TestUser", Email = "test@example.com" };
var result = await this.userManager.CreateAsync(user, "123456");
if (result.Succeeded == false)
{
foreach (var error in result.Errors)
{
Console.WriteLine(error.Description);
}
}
else
{
Console.WriteLine("Done.");
}
}
}
}
回答2:
In my Console Application (Used for background tasks), I want to create users, but how I can have access to UserManager object in a Console Application (Or in a .NET Core Class Library) ?
Same as you do it in ASP.NET Core. You just need to bootstrap it yourself. Inside your Main
(which is the console applications composition root - the earliest point where you can set up your object graph).
Here you create a ServiceCollection
instance, register the services and build the container, then resolve your app entry point. From there, anything else goes via DI.
public static int Main(string[] args)
{
var services = new ServiceCollection();
// You can use the same `AddXxx` methods you did in ASP.NET Core
services.AddIdentity();
// Or register manually
services.AddTransient<IMyService,MyService();
services.AddScoped<IUserCreationService,UserCreationService>();
...
// build the IoC from the service collection
var provider = services.BuildServiceProvider();
var userService = provider.GetService<IUserCreationService>();
// we can't await async in Main method, so here this is okay
userService.CreateUser().GetAwaiter().GetResult();
}
public class UserCreationService : IUserCreationService
{
public UserManager<ApplicationUser> userManager;
public UserCreationService(UserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public async Task CreateUser()
{
var user = new ApplicationUser { UserName = "TestUser", Email = "test@example.com" };
var result = await _userManager.CreateAsync(user, model.Password);
}
}
In practice the first class you resolve wouldn't be your UserCreationService
but some MainApplication
class, which is the core of your application and responsible for keeping the application alive as long as the operation happens, i.e. if its a background worker you run some kind of host (Azure Web Job Host etc.) which keeps the application running so it can receive events from outside (via some message bus) and on each event starts a specific handler or action, which in turn resolves other services etc.
回答3:
I know this answer is late, but other people might benefit.
You are seriously overcomplicating things using services etc. You can just do:
var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
var manager = new ApplicationUserManager(userStore);
var result = await manager.Create(user, password);
If you still want all the password validation functionality just add it to the constructor of ApplicationUserManager
来源:https://stackoverflow.com/questions/40605950/create-an-user-in-a-console-net-core-application