Simple Injector Identity UserManager Registration Error

后端 未结 1 1707
我寻月下人不归
我寻月下人不归 2021-01-14 08:43

I am following Onion Architecture and using Identity Framework. In my Core project, I have:

public interface IUserRepository : IDisposable
{
     // Reposito         


        
相关标签:
1条回答
  • 2021-01-14 09:15

    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.

    0 讨论(0)
提交回复
热议问题