首页 文章

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

提问于
浏览
1

我正在使用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.

The problem

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

1 回答

  • 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看看 .

相关问题