2
votes

I'm trying to configure Autofac to play nice with my Web API/Oauth Identity project, but it does not seem to work. I keep getting the 'cannot resolve parameter ApplicationUserManager on constructor ....'

This is the service which doesn't get instantiated:

public class EmployeeService : Service<Employee>, IEmployeeService
{
    private readonly ApplicationUserManager _userManager;

    public EmployeeService(IUnitOfWork uow, ApplicationUserManager userManager)
        : base(uow)
    {
        _userManager = userManager;
    }

    // .. other code
}

The ApplicationUserManager:

public class ApplicationUserManager : UserManager<Employee>
{
    public ApplicationUserManager(IUserStore<Employee> store, IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
    {
        this.EmailService = new EmailService();

        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            this.UserTokenProvider = new DataProtectorTokenProvider<Employee>(dataProtectionProvider.Create("ASP.NET Identity"))
            {
                //Code for email confirmation and reset password life time
                TokenLifespan = TimeSpan.FromHours(6)
            };
        }

        // UserValidator and PasswordValidator
        // ...
    }
}

And the autofac configuration:

public static void RegisterAutofac()
{
    var builder = new ContainerBuilder();

    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    builder.RegisterAssemblyTypes(typeof(IRepository<>).Assembly).AsClosedTypesOf(typeof(IRepository<>));

    builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
        .Where(t => t.Name.EndsWith("Service"))
        .AsImplementedInterfaces();

    // Tried, doesn't work:
    //builder.RegisterType<MyContext>();
    //builder.RegisterType<UserStore<Employee>>().AsImplementedInterfaces();
    //builder.RegisterType<ApplicationUserManager>().As<UserManager<Employee>>();

    // Also doesn't work:
    builder.RegisterInstance(new MyContext());
    builder.RegisterType<UserStore<Employee>>().AsImplementedInterfaces().InstancePerRequest();
    builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => 
        new IdentityFactoryOptions<ApplicationUserManager>()
        {
            DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationN‌​ame")
        }); 
    builder.RegisterType<ApplicationUserManager>().As<UserManager<Employee>>().InstancePerRequest();

    builder.RegisterType<UnitOfWork>().As<IUnitOfWork>();

    var container = builder.Build();

    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    var resolver = new AutofacWebApiDependencyResolver(container);
    GlobalConfiguration.Configuration.DependencyResolver = resolver;
}

The folllowing did work, but doesn't use DI:

public class EmployeeService : Service<Employee>, IEmployeeService
{
    private readonly ApplicationUserManager _userManager;

    public EmployeeService(IUnitOfWork uow)
        : base(uow)
    {
        var store = new UserStore<Employee>(Uow.GetDbContext());
        _userManager = new ApplicationUserManager(store);
    }
}

Anyone knows what I'm doing wrong?

(Can provide more code if more information is needed)

EDIT

Exception message & stacktrace:

exceptionMessage: "None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'AngularMVC.Services.EmployeeService' can be invoked with the available services and parameters: Cannot resolve parameter 'AngularMVC.DAL.ApplicationUserManager userManager' of constructor 'Void .ctor(AngularMVC.DAL.IUnitOfWork, AngularMVC.DAL.ApplicationUserManager)'." exceptionType: "Autofac.Core.DependencyResolutionException" stackTrace: " at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.b__0() at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate() at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable1 parameters) at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable1 parameters) at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType) at Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"

1
I don't see any registrations for ApplicationUserManager in your configuration, only for UserManager<Employee>. You will have to make an registration for ApplicationUserManager as service type (so by calling As<ApplicationUserManager>()). - Steven
If I do builder.RegisterType<ApplicationUserManager>().As<ApplicationUserManager>() I get the error "The entity type Employee is not part of the model for the current context." - devqon

1 Answers

1
votes

This is how I have registered ApplicationUserManager in Autofac, which works for all my applications.

builder.Register(c => HttpContext.Current.GetOwinContext().GetUserManager).As<ApplicationUserManager>();

This will say to Autofac that when I ask for an ApplicationUserManager, please get the UserManager from the OwinContext in my Current HttpContext.

This takes the logic and the dependecy on an OwinContext and HttpContext out of the classes, and makes the code much nicer to work with.

You can also do the same for an IAuthenticationManager, to remove your OwinContext dependency also with

builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();