Search code examples
c#dependency-injectionasp.net-identity

Unable to resolve service for type IdentityUserManager while attempting to activate login controller


I'm trying to call a login function in my LoginController. I'm using Identity Framework, but I'm having issues getting the dependencies to resolve.

I've tried extending the default interfaces to my own classes, and I've just tried using the defaults. I don't think I have the correct understanding of what's happening when the dependencies are injected.

IdentityUserManager is my customer User Manager that extends the default Identity User manager. DataContext extends IdentityDBContext.

LoginController

   [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
    public class LoginController : Controller
    {
        #region Private Fields

        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly IdentityUserManager _identityUserManager;
        private readonly IDataContext _context;

        #endregion

        #region Constructors

        public LoginController(SignInManager<IdentityUser> signInManager, IdentityUserManager identityUserManager, IDataContext context)
        {
            this._signInManager = signInManager;
            this._identityUserManager = identityUserManager;
            this._context = context;
        }

My IdentityUserManager class. The IIdentityUserManager interface doesn't do anything besides specify my 3 custom methods.

  public class IdentityUserManager : UserManager<IdentityUser>, IIdentityUserManager
    {
        private readonly IDataContext _context;
        private readonly ILDAPUserManager _ldapUserManager;
        private IUserStore<IdentityUser> _userStore;

        /// <summary>
        /// Constructor for Identity User Manager
        /// </summary>
        /// <param name="context">Data context</param>
        /// <param name="userStore">Provides abstraction for store that manages user accounts</param>
        /// <param name="identityOptions">Retrieves identity options</param>
        /// <param name="passwordHasher">Abstraction for hashing passwords</param>
        public IdentityUserManager(ILDAPUserManager ldapUserManager, IDataContext context, IUserStore<IdentityUser> userStore): base(userStore, null, null, null, null, null, null, null, null)
        {
            this._ldapUserManager = ldapUserManager;
            this._context = context;
            this._userStore = userStore;
        }

From my startup.cs

 services.AddIdentityCore<IdentityUser>(); // .AddEntityFrameworkStores<DataContext>();
            services.AddDbContext<IDataContext, DataContext>();
            services.AddScoped<ILDAPUserManager, LDAPUserManager>();
            services.AddScoped<UserManager<IdentityUser>, IdentityUserManager>();
            services.AddScoped<IUserStore<IdentityUser>, IdentityUserStore>();
            services.AddTransient<SignInManager<IdentityUser>>();
            services.AddTransient<IDbConfig, DataContextFactory>();

This is the error message that gets thrown

System.InvalidOperationException: Unable to resolve service for type 'CareInTime.Service.Controllers.IdentityUserManager' while attempting to activate 'CareInTime.Service.Controllers.LoginController'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

Solution

  • You registered IdentityUserManager as UserManager<IdentityUser>

     services.AddScoped<UserManager<IdentityUser>, IdentityUserManager>();
    

    Which mean the container knows to resolve UserManager<IdentityUser> to IdentityUserManager

    The controller constructor

    public LoginController(SignInManager<IdentityUser> signInManager, 
        IdentityUserManager identityUserManager, 
        IDataContext context
    ) { ...
    

    asks for IdentityUserManager explicitly but the container does not know how to resolve that type based on what was registered at startup.

    So either update the constructor to expect what was registered at startup or add IdentityUserManager to the service collection

    //...
    
    services.AddScoped<IdentityUserManager>();
    
    //...
    

    so it can be injected directly.