How to register custom UserStore & UserManager in DI
I am now on ASP.NET Core 1.1 and this behavior has been fixed.
I can easily implement my own UserManager and UserStore, then bootstrap the app as following:
// identity models
services
.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddUserManager<ApplicationUserManager>()
.AddUserStore<ApplicationUserStore>()
.AddDefaultTokenProviders();
and inject both UserManager and UserStore into my Controller, without any problem:
public AccountController(
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IHttpContextAccessor httpContextAccessor,
ApplicationUserManager userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_interaction = interaction;
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_account = new AccountService(_interaction, httpContextAccessor, clientStore);
}
DI in general is intended for interface-driven development; .AddUserManager<ApplicationUserManager>()
specifies an implementation UserManager<>
, not the service interface. That means that it's still expecting you to get UserManager<ApplicationUser>
and only use it that way; it'll give you an ApplicationUserManager
.
I'm assuming that you have additional methods you want to use on your ApplicationUserManager
. If not, just use the dependency constructor the way it works and enjoy the interface-driven development. If so, you have 3 options:
Use extension via composition rather than inheritance. Rather than inheriting from
UserManager<>
, writeApplicationUserManager
as a wrapper class; you can include it in the constructor. This should give you all the functionality you need inside of theApplicationUserManager
.Add it as-is to the DI framework yourself. This isn't as difficult as it sounds, since the
UserManager<>
has no real state itself:services.AddScoped<ApplicationUserManager>();
The disadvantage here is that you'll actually have two
UserManager<>
objects for the user's scope; there could be some inefficiencies as a result. From the state of the current code, I don't think it is.Write it as extension methods. If you have a number of dependencies and not just the
UserManager<>
's base functionality, this could be really complex.