I have already researched a number of errors based on the message "Make sure that the controller has a parameterless public constructor" and those answers did not appear to help. (see bottom)
Building an ASP.NET WEB API 2 application using Ninject. I want to have an applicationController which will be polled from an Angular service to allow sharing some information across sessions. To accomplish this I have built an applicationService designed to be run as a singleton so that each web api session will share the same service. I am using Ninject 3.2.0.0 and have installed (using NPM based on these instructions)
- Ninject
- Ninject.Web.Common
- Ninject.Web.WebApi
- Ninject.Web.WebApi.WebHost
Which, by design, created the NinjectWebCommon where I have added the (I believe) necessary bindings. During an initial request the applicationService is instantiated (as expected), but when the call is made to the GET method of the applicationController I get:
An error occurred when trying to create a controller of type 'ApplicationController'. Make sure that the controller has a parameterless public constructor.
the stack trace reveals:
at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
The fact that it is calling DefaultHttpControllerActivator makes me think that the Ninject Bindings are not correct, but the the only way the applicationService could be instantiated would be due to ninject.
The bindings in 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>());
}
}
the 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);
}
}
}
and finally, the 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);
}
...
}
(note: once I have this working more complex functionality will be added...but I need this working first...)
Other research: Parameterless constructor error with Ninject bindings in .NET Web Api 2.1 (I have the correct references and a public c'tor)
Ninject Web Api "Make sure that the controller has a parameterless public constructor." (& several similar) (As I understand it, WebActivatorEx and NinjectWebCommon resolve this matter)