依赖项未正确注入 mvc 5、owin、unity

Dependencies not getting injected properly mvc 5, owin, unity

我正在使用 ASP.NET MVC 5、EF6、ASP.NET Identity 和 Unity 作为 IoC,我想使用 Identity 框架提供的功能来处理用户和注册,因为我正在建立一个网站。

Startup.cs

public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }

    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(DbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);



        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Auth/Login"),
            Provider = new CookieAuthenticationProvider
             {
                 // Enables the application to validate the security stamp when the user logs in.
                 // This is a security feature which is used when you change a password or add an external login to your account.  
                 OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
             }
        });
    }



}

IdentityConfig.cs

public class EmailService : IIdentityMessageService
    {
        public async Task SendAsync(IdentityMessage message)
        {
            await configSendGridasync(message);
        }

    private async Task configSendGridasync(IdentityMessage message)
    {
        var myMessage = new SendGridMessage();
        myMessage.AddTo(message.Destination);
        myMessage.From = new System.Net.Mail.MailAddress("John@Smith.ko", "JOhn Smith");
        myMessage.Subject = message.Subject;
        myMessage.Text = message.Body;
        myMessage.Html = message.Body;

        var creds = new NetworkCredential("user", "pass");

        var transport = new Web(creds);

        if (transport != null)
        {
            await transport.DeliverAsync(myMessage);
        }
        else
        {
            Trace.TraceError("Failed to create Web transport.");
            await Task.FromResult(0);
        }
    }
}


// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application.
public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store)
        : base(store)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<DbContext>()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = false,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = false,
        };

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

        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));

        }
        return manager;
    }
}

// Configure the application sign-in manager which is used in this application.
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
    public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
        : base(userManager, authenticationManager)
    {
    }

    public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
    {
        return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
    }

    public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
    {
        return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
    }
}

public class ApplicationRoleManager : RoleManager<IdentityRole>
{
    public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
        : base(roleStore)
    {
    }
    public static ApplicationRoleManager Create(
        IdentityFactoryOptions<ApplicationRoleManager> options,
        IOwinContext context)
    {
        var manager = new ApplicationRoleManager(
            new RoleStore<IdentityRole>(
                context.Get<DbContext>()));

        return manager;
    }
}

UnityConfig.cs

public class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });

    /// <summary>
    /// Gets the configured Unity container.
    /// </summary>
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }
    #endregion

    public static void RegisterTypes(IUnityContainer container)
    {
        #region AutoMapper DI
        var config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile<AutoMapperWebProfileConfiguration>();
        });

        var mapper = config.CreateMapper();
        container.RegisterInstance(config.CreateMapper());

        #endregion

        #region userManager and roleManager DI 
        var accountInjectionConstructor = new InjectionConstructor(new DbContext());
        container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(accountInjectionConstructor);
        container.RegisterType<IRoleStore<IdentityRole, string>,
            RoleStore<IdentityRole, string, IdentityUserRole>>(accountInjectionConstructor);

        #endregion

        #region AuthenticationManager
        container.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication));

        #endregion
        #region IdentityConfig injects
        container.RegisterType<DbContext>();
        container.RegisterType<ApplicationSignInManager>();
        container.RegisterType<ApplicationUserManager>();
        container.RegisterType<EmailService>();
        container.RegisterType<IMappingEngine>(new InjectionFactory(_ => Mapper.Engine));
        #endregion


   }
}

AuthController.cs

public class AuthController : Controller
{

    private IMapper mapper;
    private RoleManager<IdentityRole> roleManager;
    private IAuthenticationManager authManager;
    private ApplicationUserManager userManager;
    private ApplicationSignInManager signInManager;

    public AuthController(IMapper mapper, IRoleStore<IdentityRole, string> roleStore, IAuthenticationManager authManager, ApplicationUserManager userManager, ApplicationSignInManager signInManager)
    {
        this.mapper = mapper;
        this.roleManager = new RoleManager<IdentityRole>(roleStore);
        this.authManager = authManager;
        this.userManager = userManager;
        this.signInManager = signInManager;

    } //rest omitted for brevity.

问题

当我 运行 代码时,Startup.cs 中的所有内容都被执行并且所有对象都从 IdentityConfig.cs 中实例化,所以我得到了一个 UserManager 实例,它具有所有需要的属性集(电子邮件服务、userTokenprovider 等),但是当到达我的控制器时,将注入另一个没有设置这些属性的对象,因此我得到很多异常(例如 IUserTokenProvider 未注册等)。我假设注入到 Controller 中的 UserManager 是 Unity 注入的那个,而不是 Startup.cs 创建的那个。与控制器中定义的其余私有属性相同。 我如何告诉 Unity 使用 Startup.cs?

创建的对象

显然,OWIN 和 Unity 在您的代码中创建了自己的 Identity 对象,因此根据使用情况,您会收到不同的对象。为避免这种情况,您必须决定由 OWIN 还是 Unity 负责创建您的对象。既然建议让 DI 做这样的事情,那么改变你的启动文件会更好:

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

现在 OWIN 从 Unity 获取相同的对象。但是您还需要一些额外的配置和考虑才能将 Unity 与 Identity 集成。 看看。