C# 使用Ninject OWIN中间件在OWIN启动中注入依赖项UserStore
在使用OWIN请求管道创建ApplicationUserManager时,使用依赖项注入创建自定义UserStore时遇到问题 背景 我正在尝试将web应用程序中的用户功能从使用SimpleMembership迁移到新的ASP.NET标识。启动新的MVC5项目时,单页应用程序的默认实现使用ASP.Identity,使用实体框架实现UserStore功能 在我的例子中,我们已经使用NHibernate作为ORM,并使用ninject实现工作单元模式,这样每个请求都有一个NHibernate会话,我想让ASP.Identity与我们现有的框架一起工作 为此,我创建了一个自定义UserStore,它可以通过注入相关的存储库/nhibernate会话等来创建。然后可以使用Ninject将其注入控制器的构造函数中,而不是使用默认实现的GetOwinContext功能 为了做到这一点,我在启动的ConfigureAuth(IAppBuilder app)方法中注释掉了以下行,该方法默认创建UserManager类:C# 使用Ninject OWIN中间件在OWIN启动中注入依赖项UserStore,c#,asp.net,dependency-injection,ninject,owin,C#,Asp.net,Dependency Injection,Ninject,Owin,在使用OWIN请求管道创建ApplicationUserManager时,使用依赖项注入创建自定义UserStore时遇到问题 背景 我正在尝试将web应用程序中的用户功能从使用SimpleMembership迁移到新的ASP.NET标识。启动新的MVC5项目时,单页应用程序的默认实现使用ASP.Identity,使用实体框架实现UserStore功能 在我的例子中,我们已经使用NHibernate作为ORM,并使用ninject实现工作单元模式,这样每个请求都有一个NHibernate会话,我
// app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
但是,Ninject.Web.Common.OwinHost没有公开其内核,因此我无法使用服务位置模式将值注入Create回调中的自定义UserStore
我还尝试创建一个单例内核,并使用app.CreatePerOwinContext(CreateKernel)向相关委托注册该内核,以便以后可以访问该内核,但当我调用context.Get()时,它只返回null
问题
如何使用CreatePerOwinContext注册回调函数来创建使用自定义UserStore的自定义UserManager,然后使用Ninject在创建回调中使用依赖项注入来创建自定义UserStore,以便我还可以访问Owin用于注入用户令牌提供程序的IdentityFactoryOptions 有关信息:
可以将内核注册为单例,以便ninject中间件可以使用相同的内核,并且也可以在owin上下文中注册
public static StandardKernel CreateKernel()
{
if (_kernel == null)
{
_kernel = new StandardKernel();
_kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
_kernel.Load(Assembly.GetExecutingAssembly(), Assembly.Load("Super.CompositionRoot"));
}
return _kernel;
}
公共静态标准内核CreateKernel()
{
if(_kernel==null)
{
_内核=新的标准内核();
_kernel.Bind().To();
_Load(Assembly.getExecutionGassembly(),Assembly.Load(“Super.CompositionRoot”);
}
返回内核;
}
回调函数app.CreatePerOwinContext(ApplicationUserManager.Create)将调用ApplicationUserManager.Create,而不是注册它以便在安装过程中稍后调用。因此,需要在ApplicationUserManager的创建回调之前注册CreateKernel函数,否则,如果您试图从该方法内的owin上下文中获取内核,则会出现空引用异常
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(CreateKernel);
app.UseNinjectMiddleware(CreateKernel);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
public void ConfigureAuth(IAppBuilder应用程序)
{
app.CreatePerOwinContext(CreateKernel);
app.usenject中间件(CreateKernel);
app.CreatePerOwinContext,但不知道在请求完成时提交任何未完成事务的最合适方式。注意这是针对WebApi的(使用System.Web.Http
)
好吧,我使用了System.Web
中的东西,这是一种欺骗,我们本应该将自己从这个名称空间中剔除,但尽管它仍然被使用,为什么不呢
首先,我使用了这个问题的一些助手:
其中,解析器已在System.Web
的全局配置中注册。因此,我只需在需要时抓取它:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var repository = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver
.GetService(typeof(Data.Repositories.UserRepository)) as Data.Repositories.UserRepository;
var manager = new ApplicationUserManager(repository);
...
我已经查看、查看并反映了libs,但找不到该方法!如果我知道该方法是如何工作的,我们可能会找到另一种方法来创建令牌,即不需要选项实例。我不知道Ninject中是否自发布以来发生了更改,但当您在UseNin注册CreateKernel
时jectMiddleware
我得到错误:System.InvalidOperationException:序列不包含任何元素
来自NinJectMVHttpApplicationPlugin
@ShayNissel你知道为什么会得到一个序列不包含元素的错误吗?我遇到了同样的问题。@Riddle Methis你看到序列不包含元素了吗错误?@thebringking我无法用UseinjectMiddleware
解决这个问题,我假设(由于缺乏适当的文档),它从未针对MVC5进行过完全修改和测试,只是针对WebAPI。为什么app.CreatePerOwinContext(CreateKernel);
和app.UseinjectMiddleware(CreateKernel)
?当我这样做时,它会弄乱绑定。我可以第一次从ninject获取绑定,但第二次尝试总是失败。删除CreatePerOwinContext
似乎可以解决它。
public static StandardKernel CreateKernel()
{
if (_kernel == null)
{
_kernel = new StandardKernel();
_kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
_kernel.Load(Assembly.GetExecutingAssembly(), Assembly.Load("Super.CompositionRoot"));
}
return _kernel;
}
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(CreateKernel);
app.UseNinjectMiddleware(CreateKernel);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var kernel = context.Get<StandardKernel>();
var userStore = kernel.Get<IUserStore<User, int>>();
var manager = new ApplicationUserManager(userStore);
//...
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var repository = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver
.GetService(typeof(Data.Repositories.UserRepository)) as Data.Repositories.UserRepository;
var manager = new ApplicationUserManager(repository);
...
public void ConfigureAuth(IAppBuilder app)
{
// Dependency Injection
Evoq.AppName.Configuration.Ninject.NinjectHttpContainer.RegisterAssembly();
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
...
/// <summary>
/// Registers a callback that will be invoked to create an instance of type T that will be stored in the OwinContext which can fetched via context.Get
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="app"></param>
/// <param name="createCallback"></param>
/// <returns></returns>
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app, Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback) where T : class,IDisposable {
if (app == null) {
throw new ArgumentNullException("app");
}
if (createCallback == null) {
throw new ArgumentNullException("createCallback");
}
app.Use(typeof(IdentityFactoryMiddleware<T, IdentityFactoryOptions<T>>),
new IdentityFactoryOptions<T>() {
DataProtectionProvider = app.GetDataProtectionProvider(),
Provider = new IdentityFactoryProvider<T>() {
OnCreate = createCallback
}
});
return app;
}