11

I have ApplicationUserManager defined like this:

public class ApplicationUserManager : UserManager<ApplicationUser, int>
    { 
        public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
        : base(store)
        {
        }

       public override Task<IdentityResult> CreateAsync(ApplicationUser user, string password)
        {
            var result = base.CreateAsync(user, password);
            //... 
            Repository.DoSomething(...); //Repository is null here
            //..
        }          

       [Dependency]
       public IRepository Repository { get; set; }
    }

For some reason my repository in not getting injected. Repository is always null

I also have this line in my unity configuration

.RegisterType<ApplicationUserManager>(new HierarchicalLifetimeManager())

How to make it injected?

UPDATE N:

This is code from my controller; How I am getting UserManager:

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
         //calling my implemintation
         IdentityResult result = await UserManager.CreateAsync(...);
    }

My current unity config

.RegisterType<IUserStore<ApplicationUser, int>, CustomUserStore>(new HierarchicalLifetimeManager())
.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication))
.RegisterType<UserManager<ApplicationUser, int>, ApplicationUserManager>()
.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager())
.RegisterType<AccountController>(new InjectionConstructor())
.RegisterType<ApplicationDbContext>(new HierarchicalLifetimeManager())
.RegisterType<ApplicationUserManager>()

UPDATE N+1:

As I find out Unity.Mvc package is not injecting WebApi controllers. I used this method in order to inject WebApi controllers. I was trying to remove Unity.Mvc package but got Identity throwing errors. From my understanding because Unity was not able to instantiate some Identity types however they were being configured and worked in the case of setting Mvc container. So I brought back the Unity.Mvc package to inject my Identity types. Otherwise, as I explained above, it is throwing different kind on null refs when Unity resolving Identity types.

So I have two containers now in my project Unity.Mvc injection DependencyResolver.SetResolver(new UnityDependencyResolver(container)); that needed to resolve Identity types and custom WebApi injection config.DependencyResolver = new UnityResolver(container); container that needed to inject WebApi contorllers both using same UnityConfig.

UPDATE 3:

I've changed this:

app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

to this

app.CreatePerOwinContext(() => UnityConfig.GetConfiguredContainer().Resolve<ApplicationUserManager>());

in Startup.ConfigureAuth() and now I my WebApi container is fully working and constructing all required Identity types so I can disable Mvc container or even completely can remove Unity.Mvc package.

Thanks to @Sam Farajpour Ghamari for clerifying lots of things.

Jeppe
  • 1,424
  • 2
  • 15
  • 36
Sergino
  • 10,128
  • 30
  • 98
  • 159
  • How you access `ApplicationUserManager` object instance? – Sam FarajpourGhamari Aug 29 '15 at 17:13
  • @SamFarajpourGhamari yes I can enter to debug my custom `CreateAsync()` method. But `Repository` is not injected and equal to `null` – Sergino Aug 29 '15 at 20:09
  • Do you get instance of the object by calling `HttpContext.GetOwinContext().Get()` method? – Sam FarajpourGhamari Aug 29 '15 at 20:17
  • @SamFarajpourGhamari Trying to call `var temt = HttpContext.Current.GetOwinContext();` but got error 'No owin.Environment item was found in the context.' – Sergino Aug 29 '15 at 20:42
  • I want to know how you get instance of ApplicationUserManager itself. Could you submit relevent code? – Sam FarajpourGhamari Aug 29 '15 at 20:53
  • OK `HttpContext.Current.GetOwinContext();` wasnt working when I try to call that in 'UnityConfig.cs' but it is working if I am calling it in `Controller`. So there is no issues with 'No owin.Environment...` I updated question wiht the code. – Sergino Aug 29 '15 at 21:26
  • @SamFarajpourGhamari Do you have anything to say about my UPDATE 3 ? Why it is working after that change? – Sergino Sep 08 '15 at 11:49

1 Answers1

25

Since you are using UserManager with OWIN. You need to integrate OWIN container with unity. Where as I don't see your other part of codes specially OWIN startup method. I show a simple example to demonstrate how you can do this by own.

First if you are using Entity Framework you must register your context to unity. Second register other type which Identity need them like this:

container.RegisterType<DbContext, MyDbContext>(new PerRequestLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>,
    UserStore<ApplicationUser>>(new PerRequestLifetimeManager());
container.RegisterType<ApplicationUserManager>(new PerRequestLifetimeManager());
container.RegisterType<IAuthenticationManager>(
    new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication))
container.RegisterType<ApplicationSignInManager>(new PerRequestLifetimeManager());

Then change constructor of ApplicationUserManager like this:

public ApplicationUserManager(IUserStore<ApplicationUser> store,
    IRepository repo)
        : base(store)
{
    this.Repository=repo;
    // put your other configuration here instead of putting in 
    // static ApplicationUserManagerCreate() method.
    this.UserValidator = new UserValidator<ApplicationUser>(this)
    {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = true
    };
        // Configure validation logic for passwords
    this.PasswordValidator = new PasswordValidator
    {
        RequiredLength = 6,
        RequireNonLetterOrDigit = true,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
    };

        // Configure user lockout defaults
    this.UserLockoutEnabledByDefault = true;
    this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
    this.MaxFailedAccessAttemptsBeforeLockout = 5;

    // and your other configurations
}

Now in your Startup.ConfigureAuth() method change following lines:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(EFDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
    // others
}

to:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(()=> DependencyResolver.Current.GetService<ApplicationUserManager>());
    app.CreatePerOwinContext(()=> DependencyResolver.Current.GetService<ApplicationSignInManager>());
    // other configs
}

Also we don't need ApplicationUserManager Create() and ApplicationSignInManager.Create() methods anymore and we could easily remove them, since Unity takes responsibility of create our classes now.

Now we fully integrate Identity with unity. For further and complex information I deeply encourage you to read this awesome blog post.

Sam FarajpourGhamari
  • 14,601
  • 4
  • 52
  • 56
  • I am creating `ApplicationUserManager` like this: `var manager = new ApplicationUserManager(new CustomUserStore(context.Get()));` - that is code from `IdentityConfig.cs`. How would it chnage it if I alter constructor method like you say above? – Sergino Aug 30 '15 at 19:27
  • Are you creating your user manager inside of static `ApplicationUserManager.Create()` method? – Sam FarajpourGhamari Aug 30 '15 at 19:33
  • Since we want Unity creates user manager actually we don't need `ApplicationUserManager.Create()` method anymore. Simply copy your configuration from that method to constructor a `ApplicationUserManager` except `var manager = new ApplicationUserManager(new CustomUserStore(context.Get()));` line since useless now – Sam FarajpourGhamari Aug 30 '15 at 19:42
  • Yes it is gets created inside `ApplicationUserManager.Create()` – Sergino Aug 30 '15 at 19:55
  • `Simply copy your configuration from that method to constructor...?` I guess I didn't get it. – Sergino Aug 30 '15 at 19:58
  • Our goal is to remove `ApplicationUserManager.Create()` method from our code. If you have some code inside of that method, rather than `var manager = new ApplicationUserManager(new CustomUserStore(context.Get()))`; line. Move them to constructor of `ApplicationUserManager` class. See my updated post I show some example as a clue. – Sam FarajpourGhamari Aug 30 '15 at 20:06
  • And your Unity configuration is fine now. Just need you change OWIN start up file also. – Sam FarajpourGhamari Aug 30 '15 at 20:13
  • 1
    `app.CreatePerOwinContext(() => DependencyResolver.Current.GetService());` giving me null reference exeption – Sergino Aug 31 '15 at 07:21
  • Please look and say exactly which object is null. If `Current` is null. it means you have not configured Unity bootstrapper well. – Sam FarajpourGhamari Aug 31 '15 at 14:05
  • I didn't find yet where error is trowing. Here is error pritnscreen http://snag.gy/tSte4.jpg. I set breakpoint on `UnityConfig.RegisterComponents()` and on `Startup.ConfigureAuth()` but error getting throwed before these two. Also I set breakpoint on `Application_Start()` but it hasn't being excuted either. So I cant check what is exactly `null`. – Sergino Sep 01 '15 at 10:26
  • If i uncomment `app.CreatePerOwinContext(ApplicationUserManager.Create)` insteard `app.CreatePerOwinContext(() => DependencyResolver.Current.GetService());` so this way I didnt have `null` error. – Sergino Sep 01 '15 at 10:33
  • I think Unity is configured **after** `Startup.ConfigureAuth()` called. And cause that error. Which unity package have you installed? `Unity.MVC` or other ones like `Unity.MVC4`? – Sam FarajpourGhamari Sep 01 '15 at 10:38
  • I have two unity packages installed in my `WebApi 2` project: `Unity 3.5.140` and `Unity.WebApi 5.0.1` – Sergino Sep 01 '15 at 14:48
  • Currently using this one http://stackoverflow.com/questions/19692981/httpapplication-application-start-not-firing-after-upgrade-to-web-api-2 to debug. Now I have actually to edit web.config so debugger can hit app configuraton methods I was trying to debug above – Sergino Sep 01 '15 at 14:58
  • Now I can see in debugger that `DependencyResolver.Current` - is not `null` but `DependencyResolver.Current.GetService()` returning `null` – Sergino Sep 01 '15 at 15:01
  • Also based on my research I can clearly see that Unity configured before `Startup.ConfigureAuth()` - it is called straight after all lines in `Application_Start()` is executed and `UnityConfig.RegisterComponents();` is configured in `Application_Start()` so `UnityConfig.RegisterComponents();` is gets called first – Sergino Sep 01 '15 at 15:07
  • Does that means that Unity can't create `ApplicationUserManager` which is configured like that `.RegisterType(new InjectionFactory(o => HttpContext.Current.GetOwinContext().GetUserManager()))`? Also I tried that `.RegisterType(new HierarchicalLifetimeManager())` but got same `null` exeption in `DependencyResolver.Current.GetService()` – Sergino Sep 01 '15 at 15:16
  • That is is two top lines of my `ConfigureAuth()` now: `public void ConfigureAuth(IAppBuilder app) { // Configure the db context and user manager to use a single instance per request app.CreatePerOwinContext(ApplicationDbContext.Create); //app.CreatePerOwinContext(ApplicationUserManager.Create); app.CreatePerOwinContext(() => DependencyResolver.Current.GetService()); }` – Sergino Sep 01 '15 at 15:26
  • first of all in `ConfigureAuth()` method remove `app.CreatePerOwinContext(ApplicationDbContext.Create)` and `app.CreatePerOwinContext(ApplicationUserManager.Create‌​)` we don't need them anymore. But for discovering error replace `app.CreatePerOwinContext(() => DependencyResolver.Current.GetService());` line with `app.CreatePerOwinContext(() => UnityConfig.GetConfiguredContainer().Resolve());` line. this cause we see actual exception insisted of null object. – Sam FarajpourGhamari Sep 01 '15 at 16:00
  • See [my other answer](http://stackoverflow.com/questions/31870021/cannot-figure-out-why-unity-is-not-injecting-identity-dbcontext-properly/31874084#31874084) for more info – Sam FarajpourGhamari Sep 01 '15 at 16:02
  • Also I deeply encourage you use official `Unity.MVC` package instead of others. Don't worry `Unity.MVC` works well in WebAPI too. See [my other answer](http://stackoverflow.com/questions/32235660/unity-inject-dependencies-into-mvc-filter-class-with-parameters/32248584#32248584) related for this issue. – Sam FarajpourGhamari Sep 01 '15 at 16:07
  • OK I was being confused with the Unity.WebApi package name. I thought it is varsion for WebApi. So I changed that to Unity.Mvc then I puth the line `UnityConfig.GetConfiguredContainer().Resolve()` and now it is throwing an exeption `Exception thrown: 'System.InvalidOperationException' in Microsoft.Owin.Host.SystemWeb.dll` and referencing to `.RegisterType(new InjectionFactory(o => HttpContext.Current.GetOwinContext().GetUserManager()))` with details `No owin.Environment item was found in the context` – Sergino Sep 01 '15 at 16:58
  • Just added this `.RegisterType (new InjectionFactory(o => HttpContext.Current.GetOwinContext()))` to my Unity config - but no luck – Sergino Sep 01 '15 at 17:05
  • Why you put `RegisterType(new InjectionFactory(o => HttpContext.Current.GetOwinContext().GetUserManager()))` in your unity config? Please relook my answer I did not say that. – Sam FarajpourGhamari Sep 01 '15 at 17:10
  • Unity.MVC is not injecting controllers in case of WebApi. I used this mehtod in order to inject WebApi controllers http://www.asp.net/web-api/overview/advanced/dependency-injection But Unity.MVC is actualy needed to inject Idenity stuff. So I have both things in my project Mvc injection `DependencyResolver.SetResolver(new UnityDependencyResolver(container));` that needed to resolve Identity stuff and WebApi injection `config.DependencyResolver = new UnityResolver(container);` that needed to inject WebApi contorllers both using same UnityConfig – Sergino Sep 08 '15 at 10:55
  • How could i do to use this approach in 3 layerd application? – Kob_24 Apr 12 '16 at 08:36
  • @Kob_24 noting special. All rules could be easily applied to 3 layered applications as well. Unity's configuration class actually is your composition root so you could layer your class, including Identity's classes, in any way you want and wire them in the Unity container. – Sam FarajpourGhamari Apr 12 '16 at 14:58
  • @SamFarajpourGhamari Its not working for me actually, any tutorial about it? – Kob_24 Apr 12 '16 at 15:15