Ninject with WebApi仍然呈现"确保控制器具有无参数的公共构造函数"

时间:2016-08-30 15:37:08

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

我已经根据消息研究了许多错误"确保控制器有一个无参数的公共构造函数"那些答案似乎没有帮助。 (见下)

使用Ninject构建ASP.NET WEB API 2应用程序。 我想要一个applicationController,它将从Angular服务中进行轮询,以允许跨会话共享一些信息。为了实现这一点,我构建了一个applicationService,旨在作为单例运行,以便每个web api会话将共享相同的服务。我正在使用Ninject 3.2.0.0并已安装(使用基于these instructions的NPM)

  • Ninject
  • Ninject.Web.Common
  • Ninject.Web.WebApi
  • Ninject.Web.WebApi.WebHost

根据设计,创建了NinjectWebCommon,我添加了(我相信)必要的绑定。在初始请求期间,applicationService被实例化(如预期的那样),但是当调用applicationController的GET方法时,我得到:

  

尝试创建类型的控制器时发生错误   ' ApplicationController中&#39 ;.确保控制器有一个   无参数公共构造函数。

堆栈跟踪显示:

  

在System.Linq.Expressions.Expression.New(Type type)at   System.Web.Http.Internal.TypeActivator.Create [TBASE](类型   instanceType)at   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage   请求,输入controllerType,Func`1&激活者)   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage   请求,HttpControllerDescriptor controllerDescriptor,Type   controllerType)

它调用 DefaultHttpControllerActivator 的事实让我觉得Ninject Bindings不正确,但是applicationService可以实例化的唯一方法是ninject。

NinjectWebCommon

中的绑定
    private static void RegisterServices(IKernel kernel)
   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)
        {
            kernel.Bind<ScfProvider>().ToSelf().InSingletonScope();
            kernel.Bind<ApplicationService>().ToSelf().InSingletonScope().WithConstructorArgument(kernel.Get<ScfProvider>());
            kernel.Bind<ApplicationController>().ToSelf().InRequestScope().WithConstructorArgument(kernel.Get<ApplicationService>());
        }        
    }

ApplicationService

    public sealed class ApplicationService
    {
        private readonly ICommand _scfUpdater;
        private Timer _timer;

        public ApplicationService(ScfProvider scfUpdater)
        {
            if (scfUpdater == null) throw new ArgumentNullException(nameof(scfUpdater));
            _scfUpdater = scfUpdater;
            _activeUsers = new Dictionary<string, string>();
            int scfInterval = int.Parse(ConfigurationManager.AppSettings["SCFUpdateInterval"]);
            _timer = new Timer(SCFTick, this, 0, scfInterval);
        }

#if DEBUG
        public ICommand SCFUpdater => _scfUpdater;
#endif



        private void SCFTick(object state)
        {
            _scfUpdater.Execute();
        }

        private readonly Dictionary<string, string> _activeUsers;
        public Dictionary<string, string> ActiveUsers => _activeUsers;

        public void UpdateUser(string userName, string status)
        {
            if (_activeUsers.ContainsKey(userName))
            {
                _activeUsers[userName] = status;
            }
            else
            {
                _activeUsers.Add(userName, status);
            }
        }
}

最后, applicationController

public class ApplicationController : ApiController


 {
        private readonly ApplicationService _applicationService;
        public ApplicationController(ApplicationService applicationService)
        {
            _applicationService = applicationService;
        }

        // GET: api/application
        public IHttpActionResult Get()
        {
            _applicationService.UpdateUser(User.Identity.Name, "online");
            return Ok(_applicationService.ActiveUsers);
        }
...
}

(注意:一旦我有这个工作,将添加更复杂的功能......但我需要先工作......)

其他研究: Parameterless constructor error with Ninject bindings in .NET Web Api 2.1 (我有正确的参考资料和一个公开的c&#tor;)

Ninject Web Api "Make sure that the controller has a parameterless public constructor."(&amp;几个相似) (据我所知,WebActivatorEx和NinjectWebCommon解决了这个问题)

1 个答案:

答案 0 :(得分:1)

我最近遇到了无参数构造函数的问题。 用本来可以解决但在部署时不起作用的解决方案浪费了很多时间来寻找解决方案,而我所采取的步骤就是这些。

Ninject的未安装nuget。* 仔细检查了bin文件夹并删除了所有Ninject * .dll 注释掉Ninject.Web.Common.cs文件中的所有代码,并根据需要将其重命名 保留服务绑定等。这样我就可以恢复Ninject * nuget程序包后创建的Ninject.Web.Common.cs。

然后我按照本指南进行操作,但使用了最新的Ninject * nuget版本。

https://nodogmablog.bryanhogan.net/2016/04/web-api-2-and-ninject-how-to-make-them-work-together/

不要忘记将其添加到新创建的Ninject.Web.Common中

GlobalConfiguration.Configuration.DependencyResolver =新的NinjectDependencyResolver(内核);

在返回内核之前;在私有静态CreateKernel方法中。