没有正确注入的依赖性mvc 5,owin,unity

时间:2016-03-10 09:36:33

标签: c# asp.net-mvc-5 unity-container owin asp.net-identity-2

我正在使用ASP.NET MVC 5,EF6,ASP.NET Identity和Unity作为IoC,我希望在构建网站时使用Identity框架提供的功能来操作用户和注册。< / p>

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注入的UserManager,而不是Startup.cs创建的UserManager。与控制器中定义的其他私有属性相同。 如何告诉Unity使用Startup.cs创建的对象?

1 个答案:

答案 0 :(得分:4)

显然,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集成。 I've already answered this看了。