解决依赖于OWIN WEB API Startup.cs与ninject [英] Resolving dependencies in OWIN WEB API Startup.cs with ninject

查看:1780
本文介绍了解决依赖于OWIN WEB API Startup.cs与ninject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Web阿比2应用程序,与都依赖于另一个类两大类,而我使用ninject解决的依赖关系。

I have a Web Api 2 App, with two classes that both depend on another class, and i'm using ninject to resolve the dependancies.

public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    private IUserService _userService;


    public AuthorizationServerProvider(IUserService userService)
    {
        _userService = userService;
    }

}

public class RefreshTokenProvider : IAuthenticationTokenProvider
{
    private IUserService _userService;

    public RefreshTokenProvider(IUserService userService)
    {
        _userService = userService;
    }

在startup.cs类我需要使用上述两个班,但当然我不能使用构造函数注入在启动类,因为这是初始化之前Ninject是。

In the startup.cs class i need to use the above two classes, but of course i cannot use constructor injection in the startup class, as that is initialised before Ninject is.

什么解决的办法,以使引用_tokenProvider和 _authServerProvider在ConfigureAuth方法?

What's a way around this so that the references to _tokenProvider and _authServerProvider in the ConfigureAuth method?

public class Startup
{
    private AuthorizationServerProvider _authServerProvider;        
    private RefreshTokenProvider _tokenProvider;

    public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
    public void Configuration(IAppBuilder app)
    {
       var config = new HttpConfiguration();

        app.UseNinjectMiddleware(CreateKernel);
        app.UseNinjectWebApi(config);

        ConfigureOAuth(app);

        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);

    }

    public void ConfigureOAuth(IAppBuilder app)
    {

        var oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true, //TODO: HTTPS
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = _authServerProvider, 
            RefreshTokenProvider = _tokenProvider
        };

}

这里的CreateKernel方法

Here's the CreateKernel Method

private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();


            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

和这里的地方注册我的服务

And here's where I register my services

private static void RegisterServices(IKernel kernel)
    {

        kernel.Bind<SimpleAuthorizationServerProvider>().ToSelf();
        kernel.Bind<SimpleRefreshTokenProvider>().ToSelf();

}

我遵循的ninject <一个建议href="https://github.com/ninject/Ninject.Web.Common/wiki/Setting-up-a-OWIN-WebApi-application">docs,但无济于事。

推荐答案

你会对此错误的方式。那么,部分错误的方式反正。你不能得到OWIN注入依赖到启动类。所以,你必须使用被配置为 app.UseNinjectMiddleware内核()来解决你的选择配置类。我们将用一个慵懒的内核做到这一点。

You're going about this the wrong way. Well, partially the wrong way anyways. You can't get OWIN to inject dependencies into the Startup class. So, you'll have to use the kernel that gets configured with app.UseNinjectMiddleware() to resolve your options configuration class. We'll do this with a Lazy kernel.

首先,你应该Startup.Auth.cs来配置此。此外,您已经有了一定的冗余在那里.. app.UseNinjectWebApi(配置)将调用 app.UseWebApi(配置)(见<一href="https://github.com/ninject/Ninject.Web.WebApi/blob/master/src/Ninject.Web.WebApi.OwinHost/OwinWebApiAppBuilderExtensions.cs">the来源)。我也不知道为什么你调用 WebApiConfig.Register()也因为这是通常称为的Global.asax.cs

First, you should be configuring this in Startup.Auth.cs. Also, you've got some redundancy in there.. app.UseNinjectWebApi(config) will call app.UseWebApi(config) (see the source). I also don't know why you're calling WebApiConfig.Register() there because that's typically called in Global.asax.cs

在任何情况下,它应该是这样的(我没有测试过这一点,但它应该是接近):

In any event, it should look like this (I haven't tested this, but it should be close):

首先,我们要你的内核建立移动到一个懒惰的方法,然后让你的 UseNinjectMiddleware()呼叫 Startup.Configuration ()方法使用慵懒kerel在启动类的成员。这个工作最好的,我觉得作为一个简单的lambda的委托,而不是创建一个静态CreateKernel方法。

First, we're going to move your kernel creation to a lazy method, and then have your UseNinjectMiddleware() call in Startup.Configuration() method use the lazy kerel in the Startup class as a member. This works best I think as a simple lambda delegate, rather than creating a static CreateKernel method.

<打击>

public partial class Startup
{
    private readonly Lazy<IKernel> _kernel = new Lazy<IKernel>(() =>
    {
        var kernel = new StandardKernel();

        kernel.Load(Assembly.GetExecutingAssembly());

        // here for brevity, move this to a RegisterServices or similar method,
        // 
        kernel.Bind<IOAuthAuthorizationServerOptions>()
            .To<MyOAuthAuthorizationServerOptions>();
        kernel.Bind<IOAuthAuthorizationServerProvider>()
            .To<AuthorizationServerProvider>();
        kernel.Bind<IAuthenticationTokenProvider>().To<RefreshTokenProvider>();
        kernel.Bind<IUserService>().To<MyUserService>();
        return kernel;
    });

    public void Configuration(IAppBuilder app)
    {
        app.UseNinjectMiddleware(() => _kernel.Value);
        var config = new HttpConfiguration();
        app.UseNinjectWebApi(config);

        ConfigureAuth(app);
    }
}

然后在你的ConfigureAuth()

Then in your ConfigureAuth()

public void ConfigureAuth(IAppBuilder app)
{
   // .... other auth code

   // Yes, boo hiss, service location, not much choice...
   // Setup Authorization Server
   app.UseOAuthAuthorizationServer(_kernel.Value
       .Get<MyOAuthAuthorizationServerOptions>().GetOptions());
}

然后创建一个接口:

public interface IOAuthAuthorizationServerOptions 
{
    OAuthAuthorizationServerOptions GetOptions();
};

创建您的实现:

Create your implementation:

public class MyOAuthAuthorizationServerOptions : IOAuthAuthorizationServerOptions 
{
     private IOAuthAuthorizationServerProvider _provider;
     private IAuthenticationTokenProvider _tokenProvider;

     public MyOAuthAuthorizationServerOptions(IAuthenticationTokenProvider tProvider,
         IOAuthAuthorizationServerProvider provider)
     {
         _provider = provider;
         _tokenProvider = tProvider;
     }
     public OAuthAuthorizationServerOptions GetOptions()
     {
         return new OAuthAuthorizationServerOptions()
                    {
                       AllowInsecureHttp = true, //TODO: HTTPS
                       TokenEndpointPath = new PathString("/token"),
                       AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
                       Provider = _provider, 
                       RefreshTokenProvider = _tokenProvider
                    };
     }
}

修改(15年4月6日):

一旦在此进一步的思考,我觉得延迟&LT; T&GT; 添加了一个除了引用,实际上是不必要的。这可以被修改,以达到相同的结果在更清洁的方式,例如:

Upon further thought on this, I think the Lazy<T> adds an addition reference that is really unnecessary. This can be modified to achieve the same results in a much cleaner way as such:

创建一个新的Startup.Ninject.cs类,并把它放在App_Start:

Create a new Startup.Ninject.cs class, and put it in App_Start:

public partial class Startup
{
    public IKernel ConfigureNinject(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        var kernel = CreateKernel();
        app.UseNinjectMiddleware(() => kernel)
           .UseNinjectWebApi(config);

        return kernel;
    }

    public IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());
        return kernel;
    }
}

public class NinjectConfig : NinjectModule
{
    public override void Load()
    {
        RegisterServices();
    }

    private void RegisterServices()
    {
        kernel.Bind<IOAuthAuthorizationServerOptions>()
            .To<MyOAuthAuthorizationServerOptions>();
        kernel.Bind<IOAuthAuthorizationServerProvider>()
            .To<AuthorizationServerProvider>();
        kernel.Bind<IAuthenticationTokenProvider>().To<RefreshTokenProvider>();
        kernel.Bind<IUserService>().To<MyUserService>();
    }
}

那么,在启动做到这一点:

Then, in Startup do this:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var kernel = ConfigureNinject(app);
        ConfigureAuth(app, kernel);
    }
}

最后,修改ConfigureAuth采取的第二个参数并使用它。

Finally, Modify ConfigureAuth to take the second parameter and use that instead.

public void ConfigureAuth(IAppBuilder app, IKernel kernel)
{
   // .... other auth code

   // Yes, boo hiss, service location, not much choice...
   // Setup Authorization Server
   app.UseOAuthAuthorizationServer(
       kernel.Get<MyOAuthAuthorizationServerOptions>().GetOptions());
}

这篇关于解决依赖于OWIN WEB API Startup.cs与ninject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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