2016-03-10 27 views
0

我正在使用ASP.NET MVC 5,EF6,ASP.NET身份和Unity作为IoC,并且我想使用Identity框架提供的功能来处理用户和注册,因为我正在建立一个网站。未正确注入的依赖mvc 5,owin,unity

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("[email protected]", "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的实例它具有所有需要的属性集(电子邮件服务,userToken提供者等),但是当我的控制器到达时,另一个对象被注入而没有设置这些属性,因此我得到了很多异常(例如IUserTokenProvider未注册等)。我假定注入Controller的UserManager是Unity注入的UserManager,而不是Startup.cs创建的那个。与控制器中定义的其他私有属性一样的故事。 如何告诉Unity使用由Startup.cs创建的对象?

+0

您是否尝试过使用PerRequestLifeTimeManager? https://msdn.microsoft.com/en-us/library/microsoft.practices.unity.perrequestlifetimemanager(v=pandp.30).aspx – smoksnes

+0

这样做,没有效果,仍然被注入的UserManager不一样这是在Startup.cs中创建的,我无法弄清楚它在哪里“丢失”。 – Thunderer

回答

2

显然,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与Identity进行集成。 I've already answered this有看。

+0

该文章确实帮助我解决了发现的任何问题或问题! – Thunderer