3

I'm not very experienced with Ninject, so I may have a concept completely wrong here, but this is what I want to do. I have a multi-tenant web application and would like to inject a different class object depending on what URL was used to come to my site.

Something along the lines of this, although maybe I can use .When() in the binding, but you get the idea:

    private static void RegisterServices(IKernel kernel)
    {
        var currentTenant = TenantLookup.LookupByDomain(HttpContext.Current.Request.Url.Host.ToLower());
        if (currentTenant.Foldername == "insideeu")
        { kernel.Bind<ICustomerRepository>().To<AXCustomerRepository>(); }
        else
        { kernel.Bind<ICustomerRepository>().To<CustomerRepository>(); }
...

The problem is that HttpContext.Current is null at this point. So my question is how can I get the HttpContext data in NinjectWebCommon.RegisterServices. Any direction on where I might be going wrong with Ninject would be much appreciated as well.

Thank you

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
Crob
  • 599
  • 4
  • 26

1 Answers1

6

The problem is that your binding here resolves at compile time; whereas you need it to resolve at runtime, for every request. To do this, use ToMethod:

Bind<ICustomerRepository>().ToMethod(context => 
    TenantLookup.LookupByDomain(HttpContext.Current.Request.Url.Host.ToLower()).Foldername == "insideeu" 
    ? new AXCustomerRepository() : new CustomerRepository());

This means that, every time the ICustomerRepository is called for, NInject will run the method using the current HttpContext, and instantiate the appropriate implementation.

Note that you can also use Get to resolve to the type rather than to the specific constructor:

Bind<ICustomerRepository>().ToMethod(context => 
    TenantLookup.LookupByDomain(HttpContext.Current.Request.Url.Host.ToLower())
        .Foldername == "insideeu" ?  
            context.Kernel.Get<AXCustomerRepository>() : context.Kernel.Get<CustomerRepository>()
    as ICustomerRepository);
McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • That worked great, and thanks for the explanation. I did have to cast the Get calls to the classes' interface (ICustomerRepository) or I would get a "no implicit conversion" error – Crob Aug 02 '13 at 21:07
  • @Crob sweet, glad it helped. I edited in the cast for posterity. – McGarnagle Aug 02 '13 at 21:29
  • Hi, I wish to do something similar. I am using the same repository & unit of work but the dbcontext is created per tenant passing in a different connection string for each tenant. This connection string comes from a separate authentication DB. SO my question is, should i do all that login in the ninject registerservices() ? – Yashvit Sep 16 '13 at 10:47
  • I had a totally different Ninject related problem but your answer made me actually figure out compile time vs runtime binding. – juhan_h Apr 02 '14 at 07:53