Search code examples
asp.net-mvcwcfninjectduplex-channel

Ninject: Bind ServiceHost instance for use with WCF duplex service


I'm working on a WCF service that uses a duplex channel to allow the service to call back to the client to relay an event raised by a component in the service layer. The proxy class is defined and constructed like this:

public class EvsMembershipProxy : DuplexClientBase<IMembershipProviderCallback>, IEvsMembershipProvider
{
    public EvsMembershipProxy(InstanceContext callbackInstance): base(callbackInstance)
    { 
    }
}

I need to get an instance of this class in a class that is configured using the ASP.NET membership system, so I bind it like this:

_ninjectKernal.Bind<IEvsMembershipProvider>().To<EvsMembershipProxy>();

and I inject it like this:

public class EvsMembershipProvider : MembershipProvider, IMembershipProviderCallback
{
    #region "Dependencies"
    [Inject]
    public IEvsMembershipProvider MembershipProvider { get; set; }
    #endregion
}

The configured membership provider is injected by Ninject like this:

_ninjectKernal.Inject(System.Web.Security.Membership.Provider);
_ninjectKernal.Inject(System.Web.Security.Roles.Provider);

I have tested the injection pattern with the WCF service layer without the duplex service and it works correctly. However, when I include the duplex service, Ninject fails during binding with the following error:

Error activating ServiceHostBase
No matching bindings are available, and the type is not self-bindable.
Activation path:
 4) Injection of dependency ServiceHostBase into parameter host of constructor of type InstanceContext
 3) Injection of dependency InstanceContext into parameter callbackInstance of constructor of type EvsMembershipProxy
 2) Injection of dependency IEvsMembershipProvider into property MembershipProvider of type EvsMembershipProvider
 1) Request for EvsMembershipProvider

Suggestions:
 1) Ensure that you have defined a binding for ServiceHostBase.
 2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
 3) Ensure you have not accidentally created more than one kernel.
 4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
 5) If you are using automatic module loading, ensure the search path and filters are correct.

So it looks as though I will need a binding for the ServiceHostBase class used in the EvsMembershipProxy constructor to resolve this issue. However, I don't know how to configure it. My best attempt to resolve the ServiceHostBase binding so far has been:

_ninjectKernal.Bind<ServiceHostBase>().ToMethod(c => OperationContext.Current.Host);

However this fails with a null reference exception during binding.

How do I bind the ServiceHostBase type so that this injection works?

** EDIT: simplified the original code to remove some of the EvsMembershipProxy constructor arguments which could be supplied by WCF configuration **


Solution

  • Discovered I could configure it like this.

    _ninjectKernal.Bind<IEvsMembershipProvider>()
                  .To<EvsMembershipProxy()
                  .WithConstructorArgument("callbackInstance", Membership.Provider);
    

    The configured membership provider implements the IMembershipProviderCallback interface and receives the callback from the service.