依赖项未正确注入 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 集成。 看看。
我正在使用 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 集成。