使用Ninject OWIN中间件OWIN启动依赖注入UserStore [英] Dependency injecting UserStore in OWIN startup using Ninject OWIN middleware

查看:983
本文介绍了使用Ninject OWIN中间件OWIN启动依赖注入UserStore的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题使用OWIN请求管道创建ApplicationUserManager在使用依赖注入创建自定义UserStore。

I am having problems creating a custom UserStore using dependency injection when creating an ApplicationUserManager using the OWIN request pipeline.

背景

我想从使用SimpleMembership新的ASP.NET身份迁移在我们的网页应用程序的用户的功能。当开始一个新的MVC项目5,单页的应用程序的默认实现使用ASP.Identity,使用实体框架来实现UserStore功能。

I am trying to migrate the user functionality in our web application from using the SimpleMembership to the new ASP.NET Identity. When starting a new MVC 5 project, the default implementation of the single page application uses ASP.Identity, using Entity Framework to implement the UserStore functionality.

在我的情况下,我们已经使用NHibernate作为ORM,以及使用ninject,使我们不得不每次请求的NHibernate会话来实现工作模式的单位,我想使ASP.Identity与我们现有的框架而努力

In my case, we are already using NHibernate as the ORM, and using ninject to implement the unit of work pattern so that we had one NHibernate session per request, and I wanted to make the ASP.Identity work with our existing framework.

为此,我创建了一个自定义的UserStore,这可能是由注射相关的资料库/ NHibernate的会议等使用Ninject,而不是使用默认的实现的GetOwinContext功能这可能再注入控制器的构造函数来创建。

To this end, I created a custom UserStore, which could be created by injecting the relevant repositories/nhibernate session, etc. This could then be injected into the Controller's constructor using Ninject, rather than using the default implementation's GetOwinContext functionality.

在为了做到这一点,我已经注释掉在启动,默认情况下创建的UserManager类的ConfigureAuth(IAppBuilder应用程序)的方法下面一行:

In order to do this, I had commented out the following line in the ConfigureAuth(IAppBuilder app) method of the Startup, which by default creates the UserManager class:

// app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

相反,我用了NinjectWebCommon安装Ninject.Web.Common.Webhost的NuGet包来创建相应的绑定时创建的。

Instead, I used the NinjectWebCommon created when installing the Ninject.Web.Common.Webhost nuget package to create the relevant bindings.

本实施工作得很好与一些的UserManager操作,但也有一些操作,如ResetPasswordAsync,它失败,因为默认ApplicationUserManager实现不叫,所以在的UserManager类UserTokenProvider从未设置:

This implementation worked fine with some of the UserManager operations, but with some operations, such as ResetPasswordAsync, it fails because the default ApplicationUserManager implementation is not called, and so the UserTokenProvider in the UserManager class is never set:

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
        // 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 = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
        // You can write your own provider and plug in here.
        manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is: {0}"
        });
        manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is: {0}"
        });
        manager.EmailService = new EmailService();
        manager.SmsService = new SmsService();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }

因此​​,UserTokenProvider未设置。

Therefore, the UserTokenProvider is not set.

问题

我想使用的OWIN管道,因为Visual Studio的的ApplicationUserManager类的默认实现注入了IDataProtectionProvider在其创建回调方法。不过,我也想用依赖注入创造我的UserStore,我不知道如何使用依赖注入这种方法中创建一个UserStore。

I want to use the OWIN pipeline, because Visual Studio's default implementation of the ApplicationUserManager class injects the IDataProtectionProvider in its Create callback method. However, I also want to create my UserStore using dependency Injection, and I do not know how to create a UserStore within this method using dependency injection.

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        // WANT TO CREATE THE USER STORE USING NINJECT DEPENDENCY INJECTION HERE
        // var userStore = ...
        var manager = new ApplicationUserManager(userStore);
    }

我曾尝试使用Ninject.Web.Common.OwinHost的NuGet包和​​创建启动类中的内核来绕过这个限制。

I have tried to get around this limitation by using the Ninject.Web.Common.OwinHost nuget package and creating the kernel within the Startup class.

    public void ConfigureAuth(IAppBuilder app)
    {
        // Setup

        app.UseNinjectMiddleware(CreateKernel);
    }

不过,Ninject.Web.Common.OwinHost不公开它的内核,所以我无法使用服务定位模式的价值观注入到我的自定义UserStore在创建回调。

However, the Ninject.Web.Common.OwinHost does not expose its Kernel, so I am unable to use service location pattern to inject the values into my custom UserStore in the Create callback.

我也试图创建一个单独的内核,并与有关委托注册这个用app.CreatePerOwinContext(CreateKernel),所以我以后可以访问内核,但是当我打电话context.Get(),它只是返回null。

I have also tried to create a singleton Kernel, and register this using app.CreatePerOwinContext(CreateKernel) with the relevant delegate, so I could later access the Kernel, but when I call context.Get() it just returns null.

我如何注册CreatePerOwinContext一个回调函数来创建一个使用自定义的UserStore定制的UserManager,然后用Ninject使用依赖注入在创建回调创建自定义UserStore,这样我也有机会获得IdentityFactoryOptions哪些Owin使用注入用户令牌供应商?

How can I register a callback function with CreatePerOwinContext to create a custom UserManager which uses a custom UserStore, and then use Ninject to create the custom UserStore using dependency injection in the Create callback, so that I also have access to the IdentityFactoryOptions which Owin uses to inject the user token provider?

推荐答案

有关信息:

是可能的内核注册为一个单,使得相同的内核可由ninject中间件被使用,也是owin上下文中注册

It is possible to register the kernel as a singleton so that the same kernel can be used by the ninject middleware and also registered within the owin context.

    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;
    }

回调函数app.CreatePerOwinContext(ApplicationUserManager.Create),将调用ApplicationUserManager.Create,而不是注册它在安装过程中稍后被调用。因此,CreateKernel功能需要ApplicationUserManager的创建回调之前进行注册,或者如果您尝试从方法中的owin背景下得到内核,你会得到一个空引用异常。

The callback function app.CreatePerOwinContext(ApplicationUserManager.Create), will call the ApplicationUserManager.Create rather than register it to be called at a later point during the setup. Therefore, the CreateKernel function needs to be registered before the ApplicationUserManager's Create callback or you will get a null reference exception if you try to get the kernel from the owin context within that method.

    public void ConfigureAuth(IAppBuilder app)
    {
        app.CreatePerOwinContext(CreateKernel);
        app.UseNinjectMiddleware(CreateKernel);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
     }

这将允许您访问内核的ApplicationUserManager的创建回调中创建自定义UserStore:

This will allow you to access the kernel to create a custom UserStore within the ApplicationUserManager's Create callback:

    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);
        //...
    }

我知道,在一般的依赖注入应在服务定位的青睐,但在这方面,我看不出一个办法解决吗? - 除非有人有什么更好的建议

I know that in general dependency injection should be favoured over service location, but in this context I couldn't see a way around it - unless anybody has any better suggestions?

这将允许您使用Ninject执行工作拍打的利用Ninject的InRequestScope()。OnDeactivati​​on功能单元。我知道了的UserManager类有一个<一个href=\"http://blogs.msdn.com/b/webdev/archive/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-identity.aspx\">per请求生命周期,但不知道最最最合适的方式提交要求完成所有未完成的事务。

This will allow you to use Ninject to implement the unit of work patter leveraging Ninject's InRequestScope().OnDeactivation functionality. I'm aware that the UserManager class has a per request lifetime, but didn't know the most the most appropriate way to commit any outstanding transactions on request finish.

这篇关于使用Ninject OWIN中间件OWIN启动依赖注入UserStore的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆