使用owin和ninject

时间:2016-05-16 14:15:46

标签: c# .net asp.net-web-api ninject owin

我有一个web api应用程序,我想使用 Owin Oauth Ninject ,所以我有这个配置< / p>

依赖注入器

public class NinjectDependencyResolver : IDependencyResolver
{
    private static IKernel kernel; 

    public NinjectDependencyResolver()
    {
        kernel = new StandardKernel();
       // AddBindings();
    }

    public object GetService(Type serviceType)
    {
        return kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return kernel.GetAll(serviceType);
    }

    private static void AddBindings()
    {
        kernel.Bind<INotifier>().To<Notifier>();
        kernel.Bind<IEventRepository>().To<EventRepository>();
        kernel.Bind<ICrud<Config>>().To<CrudConfig>();
        kernel.Bind<ICrud<Evenement>>().To<CrudEvent>();
        kernel.Bind<IAccount>().To<Account>();
    }



    public static Lazy<IKernel> CreateKernel = new Lazy<IKernel>(() =>
    {
        //var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
        AddBindings();

        return kernel;
    });


}

启动课程

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public static void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Configure the application for OAuth based flow
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
        };

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);

        //app.UseNinjectMiddleware(CreateKernel);
    }

    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseNinjectMiddleware(() => NinjectDependencyResolver.CreateKernel.Value);
        app.UseNinjectWebApi(config);
        ConfigureAuth(app);
    }
}

Global.cs

 protected void Application_Start()
        {
            DependencyResolver.SetResolver(new NinjectDependencyResolver());
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

我也有这门课

 public static class NinjectWebCommon 
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start() 
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        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;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
        }        
    }

我有这个api控制器:

public class AccountController : BaseController
{
    #region ctors

    public AccountController()
    {

    }
    [Inject]
    public AccountController(INotifier _notifierParam,  IAccount _IAccount)
    {
        Notifier = _notifierParam; 
        Account = _IAccount;
    }

    #endregion
}

派生自 BaseController ,它是一个没有构造函数的类。

问题是,当我调用帐户控制器的服务时,我得到了这个例外:

  

“消息”:“发生错误。”,“ExceptionMessage”:“错误   尝试创建类型的控制器时发生   '的AccountController'。确保控制器具有无参数   公共建设者。“,   “ExceptionType”:“System.InvalidOperationException”,“StackTrace”:“à   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage   请求,HttpControllerDescriptor controllerDescriptor,Type   controllerType)\ r \nà   System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage   请求)\ r \nà   System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”,   “的InnerException”:{       “消息”:“发生错误。”,       “ExceptionMessage”:“激活INotifier时出错\ r \ n没有匹配的绑定可用,类型不是   自我绑定。\ r \ n激活路径:\ r \ n 4)注入依赖性   INotifier进入参数_notifierParam类型的构造函数   AccountController \ r \ n 3)注入依赖关系AccountController   到NamedScope \ r \ n类型的构造函数的参数resolutionRoot   2)将依赖项NamedScope注入到参数resolutionRoot中   OwinNinjectDependencyResolver类型的构造函数\ r \ n 1)请求   IDependencyResolver \ r \ n \ r \ n建议:\ r \ n 1)确保你有   为INotifier定义了一个绑定。\ r \ n 2)如果绑定是在。中定义的   一个模块,确保模块已加载到内核中。\ r \ n   3)确保您没有意外创建多个内核。\ r \ n   4)如果使用构造函数参数,请确保参数   name与构造函数参数名称匹配。\ r \ n 5)如果您正在使用   自动模块加载,确保搜索路径和过滤器   正确的。\ r \ n”,       “ExceptionType”: “Ninject.ActivationException”       “StackTrace”:“àNinject.KernelBase.Resolve(IRequest request)\ r \ nNinject.Planning.Targets.Target 1.GetValue(Type service, IContext parent)\r\n à Ninject.Planning.Targets.Target 1.ResolveWithin(IContext parent)\ r \ n

  àNinject.Activation.Providers.StandardProvider.GetValue(IContext   上下文,IT目标)\ r \nà   Ninject.Activation.Providers.StandardProvider&LT;&GT; c__DisplayClass4.b__2(ITarget   目标)\ r \nà   System.Linq.Enumerable.WhereSelectArrayIterator 2.MoveNext()\r\n à System.Linq.Buffer 1..ctor(IEnumerable 1 source)\r\n à System.Linq.Enumerable.ToArray[TSource](IEnumerable 1 source)\ r \nà   Ninject.Activation.Providers.StandardProvider.Create(IContext   context)\ r \ nNinject.Activation.Context.ResolveInternal(Object   范围)\ r \ nNinject.Activation.Context.Resolve()\ r \nà   Ninject.KernelBase&LT;&GT; c__DisplayClass15.b__f(IBinding   绑定)\ r \nà   System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext()\r\n à System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable 1   来源)\ r \nà   Ninject.Web.WebApi.NinjectDependencyScope.GetService(类型   serviceType)\ r \nà   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage   请求,输入controllerType,Func`1&amp;激活者)\ r \nà   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage   请求,HttpControllerDescriptor controllerDescriptor,Type   controllerType)“}}

所以我需要知道:

  1. 出现此错误的原因是什么?
  2. 我该如何解决?

1 个答案:

答案 0 :(得分:5)

您正在混合依赖注入方法。您正在使用OWIN为Web API设置ninject中间件,但之后您正在管理OWIN之外的Web API(使用IIS管道):

protected void Application_Start()
{
    //..
    GlobalConfiguration.Configure(WebApiConfig.Register);
    //..
}

第二个错误是您正在创建多个内核,并且您的异常消息警告您要避免这种情况:

Ensure you have not accidentally created more than one kernel

首先重构您的代码。仅使用OWIN管理Web API:

public void Configuration(IAppBuilder app)
{
    var config = new HttpConfiguration();
    WebApiConfig.Register(config);
    app.UseNinjectMiddleware(() => NinjectDependencyResolver.CreateKernel.Value);
    ConfigureAuth(app);
    app.UseNinjectWebApi(config);
}

并从Global.asax.cs

中删除此行
GlobalConfiguration.Configure(WebApiConfig.Register);

然后确保您在整个应用程序生命周期内只创建一个内核。您应该只有一个内核的静态实例,并从需要它的任何其他对象引用它。