3

I'm using ASP.NET MVC 5, with Ninject 3.

I want to have some code run when the web site starts, which will pull something from the database. I already have injection set up, and it's working fine elsewhere in the project.

I changed the Global.asax file to look like this...

[Inject]
public VoucherCompanyServiceLogicInterface VoucherCompanyServiceLogic { get; set; }

protected void Application_Start() {
  AreaRegistration.RegisterAllAreas();
  FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  RouteConfig.RegisterRoutes(RouteTable.Routes);
  BundleConfig.RegisterBundles(BundleTable.Bundles);
  VoucherCompany vc = VoucherCompanyServiceLogic.GetByID(1, 1);
}

...but the VoucherCompanyServiceLogic property is always null. I copied the two lines for this (the Inject attribute and the property declaration) from another class where they work fine.

I put some Debug.WriteLine statements in this method, and in the RegisterServices method of the NinjectWebCommon class, and I can see that the services are being registered before I try to use this one, so that's not the issue.

Anyone any idea why this is always null?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Avrohom Yisroel
  • 8,555
  • 8
  • 50
  • 106
  • Great question. It's null because Ninject isn't active at that point in the application lifecycle. You'll need to slightly rethink your approach. I don't know enough about Ninject to give you a full answer. – Rowan Freeman Jul 18 '14 at 04:16
  • You should have a NinjectWebCommon file or something similar, find out when that is run, as Rowan Freeman pointed out, it probably hasn't started yet, meaning it won't be able to inject what you need at this point. You should be able to start it before your call though. – Kyle Gobel Jul 18 '14 at 04:57
  • Thanks to both of you for your replies, but if you read the penultimate paragraph of my question, you'll see that I already said that the Ninject stuff had run before the Application_Start code. The problem, as pointed out in the accepted answer was that Ninject doesn't have any involvement in the creation of the MvcApplication object, as that's created by ASP.NET itself. Thanks anyway. – Avrohom Yisroel Jul 20 '14 at 14:08

1 Answers1

2

The instance of MvcApplication is created for you by ASP.Net, Ninject can do nothing to automatically inject that property.

As you mention that injection works elsewhere in your MVC application, I am assuming you are using one of the Nuget packages that includes a NinjectWebCommon with all the plumbing needed for DI in an MVC application. The NinjectWebCommon will be run before the Application_Start event as it likely registers a PreApplicationStartMethod and apart from registering your dependencies it is also configuring an IDependencyResolver for MVC behind the scenes.

So you could use the dependency resolver in your Application_Start method to get an instance of that service:

protected void Application_Start()
{        
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    VoucherCompanyServiceLogic = DependencyResolver.Current.GetService<IVoucherCompanyServiceLogicInterface>();
    if(VoucherCompanyServiceLogic != null)
    {
        VoucherCompany vc = VoucherCompanyServiceLogic.GetByID(1, 1);
    }
}

But what are you planning to do with that VoucherCompany instance? Are you aware that multiple instances of the MvcApplication are likely to be created by ASP.Net, and Application_Start will NOT be called for every instance? See this other SO question or read this article.

That means you could end with instances of the HttpApplication class where both the service and the company are null. If you just wanted to get the company on application startup and have that object available on subsequent events, I would set VoucherCompany as static, populate it on Application_Start and wouldn't even bother to save the reference to the service. (Depending on what you want to achieve, there might be better options.)

Hope it helps!

Community
  • 1
  • 1
Daniel J.G.
  • 34,266
  • 9
  • 112
  • 112
  • Daniel, thanks for the excellent reply, and especially the explanation of the way MvcApplication works. I didn't realise that it might be called several time. As it happens, it's not a problem in my case, as I was intending to populate a static object, just as you suggested, and only use the service logic object to get the VC from the database, not hang on to it. I used the DependencyResolver to the the service logic, and it works perfectly! – Avrohom Yisroel Jul 20 '14 at 14:06
  • Glad to hear that, @Avrohom Yisroel. (The application object can be tricky!) – Daniel J.G. Jul 20 '14 at 15:34