1

I have tried to use Ninject 3 to inject "RuleChecker" into my controller, but it doesnt work.

Error "Make sure that the controller has a parameterless public constructor."

I have read most of the topics with similar issues but could not find a solution for my case.

It should be simple, but I can't figure out how to make it work. Thanks

public class CarController : ApiController
{
    private readonly IRule rule;

    public CarController(IRule rule)
    {
        this.rule = rule;
    }
}



public class RuleChecker : IRule
{

    private ICheckCar CarData { get; }
    private IRuleSet RuleSet { get; } 
    private IFactory Factory { get; }    

    public RuleChecker(ICheckCar carData, IRuleSet ruleset,
                               IFactory factory)
    {
              CareData= cardata;
              RuleSet = ruleSet;
              Factory = factory;
    }
}

Few examples what I have tried but it doesn't work

    private static void RegisterServices(IKernel kernel)
    {
           kernel. Bind<IRule>().To<RuleChecker>();
           
           //OR

           kernel.Bind<IRule>()
               .ToConstructor(
                    ctorArg => new RuleChecker(
                        ctorArg.Inject<ICarData>(),
                        ctorArg.Inject<IRuleSet>(),
                        ctorArg.Inject<IFactory>()
                    )
                );
   }

Ninject:

private static IKernel CreateKernel()
        {
            var kernel = default(IKernel);
            try
            {
                kernel = CommonDependencyRegistration.Setup();
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
                RegisterServices(kernel);
                GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
                return kernel;
            }
            catch
            {
                kernel?.Dispose();
                throw;
            }
        }

Global.asax

 public class WebApiApplication : HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);

            var config = GlobalConfiguration.Configuration;
            config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
                (new Newtonsoft.Json.Converters.StringEnumConverter());
        }
    }
Toni0123
  • 107
  • 1
  • 11
  • This "Make sure that the controller has a parameterless public constructor" typically comes from the ASP.NET framework itself, not from the DI Container. This likely means you didn't attach your DI Container correctly into the ASP.NET pipeline, but it's impossible to give you feedback on this, because you didn't show the relevant bootstrapping code for your Web API application. You should consult Ninject's documentation to see how to use it with ASP.NET Web API. – Steven Mar 25 '23 at 11:44
  • Thanks @Steven, not sure, every other controller works just fine – Toni0123 Mar 25 '23 at 15:35
  • What's likely happening is the problem that I described [here](https://stackoverflow.com/a/15910758/264697). In short, Ninject can't resolve the controller and its `IDependencyResolver` implementation returns `null`. This causes Web API to try to instantiate the controller which will succeed in case there is a default constructor. – Steven Mar 25 '23 at 17:22
  • @Steven Tried, but no luck – Toni0123 Mar 26 '23 at 06:40
  • TLDR; The solution is to register all your controllers *explicitly* in the Ninject container. Not registering the controller will cause [this line](https://github.com/ninject/Ninject.Web.WebApi/blob/a5ca708c0d1948910f25585925d6afbe9034ef23/src/Ninject.Web.WebApi/NinjectDependencyScope.cs#L63) in the `NinjectDependencyScope` to return null in case the controller can't be created because of a missing dependency. – Steven Mar 26 '23 at 09:06

2 Answers2

0

You can use ToMethod() to create an instance of RuleChecker and inject dependencies. This should do it.

Bind<IRule>().ToMethod(context =>
    new RuleChecker(
        context.Kernel.Get<ICheckCar>(),
        context.Kernel.Get<IRuleSet>(),
        context.Kernel.Get<IFactory>()
    )
);
AVTUNEY
  • 923
  • 6
  • 11
  • kernel.Bind() .To(); Tried like this, but doesn't work – Toni0123 Mar 25 '23 at 10:23
  • With above it complains about IConfigurationHandler – Toni0123 Mar 25 '23 at 10:32
  • Thanks, I have tried but I Exception that I need set "CarData" that looks like public sealed class CarData : ICarData { private readonly ServiceBase serviceBase; private readonly IConfiguration handler; public CarData(FirstService service, IConfiguration handler) { serviceBase = service; this. Handler = handler; } } – Toni0123 Mar 25 '23 at 10:35
0

ASP.Net needs the default ctor.
You need to have the controller resolved by NInject (or any other di container). Only then you can inject into controllers. s.https://stackoverflow.com/questions/14016727/how-to-use-ninject-with-asp-net-web-api

Jürgen Röhr
  • 886
  • 6
  • 10