I am following Onion Architecture and using Identity Framework. In my Core project, I have:
public interface IUserRepository : IDisposable
{
// Reposito
The exception message says:
The constructor of type UserManager<AppUser, int> contains the parameter of type IUserStore with name 'store' that is not registered. Please ensure IUserStore<AppUser, int> is registered, or change the constructor of UserManager.
The exception suggests that you should make a registration for IUserStore<AppUser, int>
, because the UserManager<AppUser, int>
depends on this. So you could for instance make the following registration:
// UserStore<TUser> is defined in Microsoft.AspNet.Identity.EntityFramework.
// Do note that UserStore<TUser> implements IUserStore<TUser, string>, so
// this Entity Framework provider requires a string. If you need int, you
// might have your own store and need to build your own IUserStore implemenation.
container.Register<IUserStore<AppUser, string>>(
() => new UserStore<AppUser>>(),
Lifestyle.Scoped);
However, according to this article, you should not auto-wire framework types such as UserManager<TUser, TKey>
, but use manual registration instead by creating such type yourself. For instance:
container.Register<UserManager<AppUser, string>>(
() => new UserManager<AppUser, string>(new UserStore<AppUser>()),
Lifestyle.Scoped);
It would be even better to refrain from using types from external libraries (such as the UserManager<TUser, TKey>
) directly in your core application. Especially since you are practicing the Onion architecture. This architecture promotes SOLID principles and describes the concept of ports and adapters. A port is an abstraction defined by your application that allows a gateway into some external domain or library. An adapter is an implementation of such abstraction that actually connects to this external domain or library. This is exactly what the Dependency Inversion Principle (one of the five SOLID principles) describes.
So instead of letting your UserRepository
depend on a framework type such as UserManager<TUser, TKey>
, let it depend on a customly defined abstraction, with a very narrowly defined and single responsibility. The adapter for this abstraction can on its turn use UserManager<TUser, TKey>
.
Depending on what UserRepository
does, you might even consider this UserRepository
itself an adapter. In this case, letting UserRepository
depend directly on UserManager<TUser, TKey>
is fine. In that case, hiding the UserManager<TUser, TKey>
behind an extra abstraction just causes an extra/needless layer of abstraction.
But nonetheless, the adapter can not only directly depend on UserManager<TUser, TKey>
, but it can simply control the creation and destruction of UserManager<TUser, TKey>
itself. In other words, your UserRepository
can look as follows:
// NOTE: Do not let IUserRepository implement IDisposable. This violates
// the Dependency Inversion Principle.
// NOTE2: It's very unlikely that UserRepository itself needs any disposal.
public class UserRepository : IUserRepository
{
// This is Identity UserManager
private readonly IAuthenticationManager _authenticationManager;
public UserRepository(IAuthenticationManager authenticationManager)
{
_authenticationManager = authenticationManager;
}
public void Delete(AppUser user) {
// Here we create and dispose the UserManager during the execution
// of this method.
using (manager = new UserManager<AppUser, string>(
new UserStore<AppUser>())) {
manager.DeleteAsync(user).Result;
}
}
}
In the Simple Injector discussions there is an interesting description about how to work with Identity and Visual Studio's default template. And here is a Stackoverflow q/a about Identity that you might find interesting as well.