12

Long story short, I'm trying to use ELMAH with MVC 2 and Ninject, and I need to use parameterless constructors. I created an initial post about it here: Using a parameterless controller constructor with Ninject?

I was advised to use property injection instead of constructor injection. So I moved from this:

public class DepartmentsController : Controller
{
    private IDepartmentsRepository departmentsRepository;

    public DepartmentsController(IDepartmentsRepository departmentsRepository)
    {
        this.departmentsRepository = departmentsRepository;
    }

    ...
}

to this:

public class DepartmentsController : Controller
{
    private IDepartmentsRepository _departmentsRepository;

    [Inject]
    public IDepartmentsRepository DepartmentsRepository
    {
        get { return _departmentsRepository; }
        set { _departmentsRepository = value; }
    }

    ...
}

But in my other controller functions, whether I try to access DepartmentsRepository or _departmentsRepository, I get an object reference not set to an instance of an object error when I try to access it.

Is there something else I need to do here?

Community
  • 1
  • 1
Steven
  • 18,761
  • 70
  • 194
  • 296
  • 6
    Are you using `Ninject.Web.Mvc`? – Daniel T. Feb 02 '11 at 02:37
  • 2
    Wait what? What is requiring you to use parameterless constructors? – John Farrell Feb 02 '11 at 05:36
  • I'm having a strange issue where a particular dependency is not resolved when the property has a specific name. It works fine if renamed, but all the other dependencies resolve as normal (and the same dependency resolves fine in other cases for the same property name). I don't have a clue why, but it's always something to try. – Morten Christiansen May 19 '11 at 11:01
  • In my class, it was because I was trying to access my injected property in the constructor. Of course, the injection can't occur until the object itself has been constructed. – neontapir Aug 23 '13 at 22:34
  • 1
    not sure why it is suggested to use setter injection over constructor injection. Martin Fowler seems to suggest constructor over setter. – liang Dec 17 '13 at 05:25

5 Answers5

11

I had a similar problem. Have a look at my questions: Using Ninject with Membership.Provider.

Basically when you initialise DepartmentsController you need to injectthis (i.e. your departments controller into your Ninject kernal. So its something like:

public class DepartmentsController : Controller
{
  private IDepartmentsRepository _departmentsRepository;

  [Inject]
  public IDepartmentsRepository DepartmentsRepository
  {
    get { return _departmentsRepository; }
    set { _departmentsRepository = value; }
  }

  public DepartmentsController()
  {
    NinjectHelper.Kernel.Inject(this);
  }
}

Where NinjectHelper in this case gets the current Ninject Kernel.

Community
  • 1
  • 1
lancscoder
  • 8,658
  • 8
  • 48
  • 68
  • 8
    this will work, but it's a better idea to use a ControllerFactory do the injection so the controller doesn't have to know about Ninject. – Dave Thieben Feb 03 '11 at 21:19
3

Try something like this:

Global.asax.cs

        protected void Application_Start()
        {
            DependencyResolver.SetResolver(
                new MyDependencyResolver(
                    new StandardKernel(
                        new MyModule())));
            //...
        }

MyDependencyResolver.cs

    public class MyDependencyResolver : IDependencyResolver
    {
        private IKernel kernel;

        public MyDependencyResolver(IKernel kernel)
        {
            this.kernel = kernel;
        }

        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }
    }

MyModule.cs

    public class MyModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IDepartmentsRepository>().To<DepartmentsRepository>();
        }
    }
frennky
  • 12,581
  • 10
  • 47
  • 63
2

There could be 2 reasons for object reference not set exception.

1) Ninject does not know how to Bind IDepartmentsRepository to a concrete implementation of DepartmentsRepository ( I doubt that is the case though )

2) If you are trying to access DepartmentsRepository property in your controller's constructor, it will throw the exception (since Ninject is only able to inject Property Dependencies after the object is constructed).

Hope that helps.

Raghu
  • 2,678
  • 2
  • 31
  • 38
0

As Daniel T. in the above comment posted, you should check out Ninject.Web.Mvc. If you use the NinjectHttpApplication in that project, it will autowire everything for you, so that when the NinjectControllerFactory constructs a new controller, it will call Inject() for you to fill the property injections.

Dave Thieben
  • 5,388
  • 2
  • 28
  • 38
0

An observation for anyone arriving here having problems "Using property injection instead of constructor injection" with Ninject even if not specifically with MVC Controllers.

Ninject will only identify the [Inject] attribute on a property and perform the property injection on classes that are being brought to life as part of a Ninject chain of DI.

If you are creating the object like this

var myObj = new MyObj();

Ninject doesn't know about the class instantiation and so won't know to perform any injection.

In the MVC world you can use

var emailer = DependencyResolver.Current.GetService<IEmailer>();

spud
  • 495
  • 5
  • 10