IdentityServer / IdentityServer3.AspNetIdentity

ASP.NET Identity support for Thinktecture IdentityServer3
Apache License 2.0
64 stars 51 forks source link

Dependency Injection and ASP.NET Identity generics #48

Closed scottbrady91 closed 9 years ago

scottbrady91 commented 9 years ago

I've seen a few people complaining about the IdentityServer (and IdentityManager) handling of ASP.NET Identity dependency injection. The issues arise from the handling of their generics and the ASP.NET teams recommendations of creating static create methods or pointlessly extending the base classes to hide the generics away, don't really help the situation.

The only way I've been able to get the DI working with the default Identity classes so far is like so:

factory.Register(new Registration<IdentityDbContext>());
factory.Register(new Registration<UserStore<IdentityUser>>());
factory.Register(new Registration<UserManager<IdentityUser, string>>(x => new UserManager<IdentityUser>(x.Resolve<UserStore<IdentityUser>>())));
factory.UserService = new Registration<IUserService, AspNetIdentityUserService<IdentityUser, string>>();

Otherwise you will get the following error when autofac tries to resolve the UserService, as it cannot resolve the UserManager constructor:

An exception of type 'Autofac.Core.DependencyResolutionException' occurred in IdentityServer3.dll but was not handled in user code

Additional information: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'IdentityServer3.AspNetIdentity.AspNetIdentityUserService`2[Microsoft.AspNet.Identity.EntityFramework.IdentityUser,System.String]' can be invoked with the available services and parameters:

Cannot resolve parameter 'Microsoft.AspNet.Identity.UserManager`2[Microsoft.AspNet.Identity.EntityFramework.IdentityUser,System.String] userManager' of constructor 'Void .ctor(Microsoft.AspNet.Identity.UserManager`2[Microsoft.AspNet.Identity.EntityFramework.IdentityUser,System.String], System.Func`2[System.String,System.String])'.

Note that if I do not explicitly state the key in the UserManager registration, the resolver will again start throwing the above error.

As you can see from my factory set up, by the time I set up the DbContext to receive a connection string, I might as well have created my own concrete factory method and feed this into the DI component directly. But I don't really feel comfortable recommending this to people when you have gone out of your way to create the component...

I know the DI and generics situation in ASP.NET Identity itself is pretty dire, but there are ways around it when you have control over the DI container (autofac or otherwise).

If there's some reason I shouldn't be using the base Identity classes that I don't know of do say, but even if I extended them I would still aim to keep the generic types from the base classes...

scottbrady91 commented 9 years ago

Can you point me to a change or reasoning?

leastprivilege commented 9 years ago

Nothing particular. Is this still an open issue. Brock has a sample on how to use ASP.NET Identity in identity server - since nothing has happened here for 2 months - I thought it is OK to close this issue.

scottbrady91 commented 9 years ago

No, the above still applies. No changes since I created the issue.