【发布时间】:2018-11-29 18:44:05
【问题描述】:
我已经根据消息“确保控制器具有无参数的公共构造函数”研究了许多错误,但这些答案似乎没有帮助。 (见底部)
使用 Ninject 构建 ASP.NET WEB API 2 应用程序。 我想要一个 applicationController,它将从 Angular 服务轮询,以允许跨会话共享一些信息。为此,我构建了一个应用程序服务,旨在作为单例运行,以便每个 Web api 会话共享相同的服务。我正在使用 Ninject 3.2.0.0 并已安装(使用基于 these instructions 的 NPM)
- 忍者
- Ninject.Web.Common
- Ninject.Web.WebApi
- Ninject.Web.WebApi.WebHost
根据设计,它创建了 NinjectWebCommon,我在其中添加了(我相信)必要的绑定。在初始请求期间, applicationService 被实例化(如预期的那样),但是当调用 applicationController 的 GET 方法时,我得到:
尝试创建类型控制器时出错 '应用程序控制器'。确保控制器具有 无参数的公共构造函数。
堆栈跟踪显示:
在 System.Linq.Expressions.Expression.New(Type type) 在 System.Web.Http.Internal.TypeActivator.Create[TBase](类型 实例类型)在 System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage 请求,类型控制器类型,Func`1& 激活器)在 System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage 请求,HttpControllerDescriptor 控制器描述符,类型 控制器类型)
它调用 DefaultHttpControllerActivator 的事实让我认为 Ninject 绑定是不正确的,但是可以实例化 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." (&几个类似的) (据我了解,WebActivatorEx 和 NinjectWebCommon 解决了这个问题)
【问题讨论】:
-
请出示您的
IDependencyResolver或IHttpControllerActivator注册。 -
我已经编辑了 NinjectWebCommon 的附加材料(上图)。我相信 CreateKernel() 方法取代了对 IDependencyResolver 或 IHttpControllerActivator 的需求。 (或者至少我在上面显示的第一个链接中提供的示例代码中没有它)
-
我认为这个 NinjectWebCommon 库是为 MVC 构建的,而不是为 Web API 构建的。
-
我所读到的其他建议(如果我删除它,NinjectWebCommon 类将不再编译......)我相信我的问题的根源在于 ninject 元素和版本以及各种文章的组合以及与彼此或我正在做的事情不太一致的样本。
标签: c# asp.net-web-api ninject