【问题标题】:Parameterless constructor issue within webapi application using owin and ninject使用 owin 和 ninject 的 webapi 应用程序中的无参数构造函数问题
【发布时间】:2016-09-12 08:54:12
【问题描述】:

我有一个 web api 应用程序,我想在其中使用 OwinOauthNinject ,所以我有这个配置

依赖注入器

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,这是一个没有构造函数的类。

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

"Message":"发生错误。", "ExceptionMessage":"错误 尝试创建类型控制器时发生 '帐户控制器'。确保控制器具有无参数 公共构造函数。", "ExceptionType":"System.InvalidOperationException", "StackTrace":"à System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage 请求,HttpControllerDescriptor 控制器描述符,类型 控制器类型)\r\n à System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage 请求)\r\n à System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()", “内部异常”:{ "Message":"发生错误。", "ExceptionMessage":"激活 INotifier 时出错\r\n没有匹配的绑定可用,并且类型不是 自绑定。\r\n激活路径:\r\n 4) 依赖注入 INotifier 转换为类型构造函数的参数 _notifierParam AccountController\r\n 3) 注入依赖AccountController 进入 NamedScope 类型的构造函数的参数 resolutionRoot\r\n 2)将依赖NamedScope注入参数resolveRoot的 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 请求)\r\n à Ninject.Planning.Targets.Target1.GetValue(Type service, IContext parent)\r\n à Ninject.Planning.Targets.Target1.ResolveWithin(IContext parent)\r\n
à Ninject.Activation.Providers.StandardProvider.GetValue(IContext 上下文,ITarget 目标)\r\n à Ninject.Activation.Providers.StandardProvider.c__DisplayClass4.b__2(ITarget 目标)\r\n à System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext()\r\n à System.Linq.Buffer1..ctor(IEnumerable1 source)\r\n à System.Linq.Enumerable.ToArray[TSource](IEnumerable1 源)\r\n à Ninject.Activation.Providers.StandardProvider.Create(IContext 上下文)\r\n à Ninject.Activation.Context.ResolveInternal(对象 范围)\r\n à Ninject.Activation.Context.Resolve()\r\n à Ninject.KernelBase.c__DisplayClass15.b__f(IBinding 绑定)\r\n à System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n à System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1 源)\r\n à Ninject.Web.WebApi.NinjectDependencyScope.GetService(类型 服务类型)\r\n à System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n à System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage 请求,HttpControllerDescriptor 控制器描述符,类型 控制器类型)"} }

所以我需要知道:

  1. 这个错误的原因是什么?
  2. 我该如何解决?

【问题讨论】:

  • 检查Notifier 类。错误消息指出Error activating INotifier
  • 还有你如何设置你的依赖解析器。
  • 您是否浏览过异常消息中的所有建议。我相信它清楚地告诉你需要检查什么来解决你的问题。注意到另一个示例Ensure you have not accidentally created more than one kernel. 我看到两个实例,您创建了一个新的kernel
  • @Nkosi 请看我的编辑

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


【解决方案1】:

您正在混合依赖注入方法。您正在使用 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);

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

【讨论】:

  • 感谢您的回答,但是当我应用您提到的更改时,我收到此异常The 'DelegatingHandler' list is invalid because the property 'InnerHandler' of 'PassiveAuthenticationMessageHandler' is not null. Nom du paramètre : handlers !!!
  • 编辑了我的答案。使用新的Startup.cs 代码重试。
  • 感谢编辑,修改后应用程序运行良好,但 web api 文档区无法发现控制器及其操作!!
  • 我看不到任何关于 Web Api documentarion 您的问题的参考资料。我建议您专门为此目的创建一个新问题。
猜你喜欢
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
  • 2015-09-25
相关资源
最近更新 更多