I have some issues with injection - that fell apart when i setup my unit test project.. It took a turn, where i named instances in the registration, which may or may not be that clean, however i felt it gave more readability.
I have a UsersController which manages users and roles in the Microsoft.AspNet.Identity
domain. It constructs like this:
class {
[InjectionConstructor]
public UsersController(
[Dependency("userManager")] UserManager userManager,
[Dependency("signInManager")] ApplicationSignInManager signInManager,
[Dependency("roleManager")] ApplicationRoleManager roleManager,
[Dependency("emailService")] IIdentityMessageService emailService)
{
RoleManager = roleManager;
UserManager = userManager;
SignInManager = signInManager;
EmailService = emailService as EmailService;
Trace.WriteLine("constructed");
}
public EmailService EmailService { get; private set; }
public ApplicationSignInManager SignInManager { get; private set; }
public UserManager UserManager { get; }
public ApplicationRoleManager RoleManager { get; }
}
The bootstrap in my Unity container goes as follows:
container
.RegisterType<IdentityDb>("identityDb", new InjectionConstructor("DefaultConnection"))
.RegisterType<RoleStore<IdentityRoleIntPk, int, UserRoleIntPk>, ApplicationRoleStore>("roleStore", new InjectionConstructor(new ResolvedParameter<IdentityDb>("identityDb")))
.RegisterType<UserStore<ApplicationUser, IdentityRoleIntPk, int, UserLoginIntPk, UserRoleIntPk, UserClaimIntPk>, ApplicationUserStore>("userStore", new InjectionConstructor(new ResolvedParameter<IdentityDb>("identityDb")))
.RegisterType<RoleManager<IdentityRoleIntPk, int>, ApplicationRoleManager>("roleManager")
.RegisterType<IIdentityMessageService, EntityEmailService>("emailService")
.RegisterType<IAuthenticationManager>("authenticationManager",
new InjectionFactory(c =>
HttpContext.Current.GetOwinContext().Authentication))
.RegisterType<SignInManager<ApplicationUser, int>, ApplicationSignInManager>("signInManager")
.RegisterType<IdentityFactoryOptions<UserManager>>("identityFactoryOptions",
new InjectionFactory(c =>
new IdentityFactoryOptions<UserManager>()
{
DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("pacientio.Application")
}))
.RegisterType<UserManager<ApplicationUser, int>, ApplicationUserManager>("userManager");
This here is how the stacktrace looks like
[ResolutionFailedException: Resolution of the dependency failed, type = "pacientio.client.Controllers.AccountController", name = "(none)". Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, Microsoft.AspNet.Identity.IIdentityMessageService, is an interface and cannot be constructed. Are you missing a type mapping?
At the time of the exception, the container was:
Resolving .AccountController,(none)
Resolving parameter "userManager" of constructor AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, ApplicationRoleManager roleManager)
Resolving ApplicationUserManager,userManager
Resolving parameter "emailService" of constructor ApplicationUserManager(pacientio.entities.IdentityConfig.ApplicationUserStore userStore, Microsoft.AspNet.Identity.Owin.IdentityFactoryOptions`1[[pacientio.entities.IdentityConfig.UserManager, pacientio.entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] options, Microsoft.AspNet.Identity.IIdentityMessageService emailService)
Resolving Microsoft.AspNet.Identity.IIdentityMessageService,emailService
My problem seems to originate from this : .RegisterType<IIdentityMessageService, EntityEmailService>("emailService")
which is used by the userManager to send login/password mails etc.
So here is Also the UserManager constructor
public class ApplicationUserManager: UserManager
{
public ApplicationUserManager(
[Dependency("userStore")] ApplicationUserStore userStore,
[Dependency("identityFactoryOptions")] IdentityFactoryOptions<UserManager> options,
[Dependency("emailService")] IIdentityMessageService emailService)
: base(userStore, options, emailService)
{
}
}
Question is.. Why the devil, doesn't the mapping IIdentityMessageService mapTo EmailService kick in? I explicitly register it with RegisterType<IIdentityMessageService, EmailService>("emailService")
and ask for it via [Dependency("emailservice")]