1

I can't seem to get these 3 working together.

I narrowed it down to a very simple service with 1 method:

[System.ServiceModel.ServiceContract]
public interface Icontract
{
    [System.ServiceModel.OperationContract]
    void Ping();
}

public class contract : Icontract
{
    public void Ping()
    { }
}

I have a factory that looks like this:

public class ServiceFactory
{
    private readonly IKernel _kernel;

    public ServiceFactory(IKernel kernel)
    {
        _kernel = kernel;
    }

    public NinjectServiceHost<T> GetService<T>()
    {
        return _kernel.Get<NinjectServiceHost<T>>();
    }
}

If I create the service like so...

_tmp = new ServiceHost(typeof(ConsoleApplication1.contract));
_tmp.Open();

...Discovery works just fine. However if I use the factory like so...

_tmp = _factory.GetService<ConsoleApplication1.contract>();
_tmp.Open();

...the service isn't discoverable anymore. Everything else about the service works as expected.

Anyone had any joy getting Discovery working this way, or is there something I'm doing wrong?

Simon Halsey
  • 5,459
  • 1
  • 21
  • 32

2 Answers2

1

It is a bug in Ninject.Extensions.Wcf.NinjectServiceBehavior class. Just create your own NinjectServiceBehaviorFixed class derived from IServiceBehavior interface with following method:

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
    foreach (EndpointDispatcher endpointDispatcher in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>().SelectMany(channelDispatcher => (IEnumerable<EndpointDispatcher>) channelDispatcher.Endpoints))
    {
        if (endpointDispatcher.DispatchRuntime.InstanceProvider == null)
        {
            endpointDispatcher.DispatchRuntime.InstanceProvider = _instanceProviderFactory(serviceDescription.ServiceType);
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(_requestScopeCleanUp);
        }
   }
}

Add to your NinjectModule code:

Unbind<IServiceBehavior>();
Bind<IServiceBehavior>().To<NinjectServiceBehaviorFixed>();

In ApplyDispatchBehavior method we just added check if endpointDispatcher.DispatchRuntime.InstanceProvider is null because WS-Discovery creates new endpoints with defined InstanceProvider which should not be overwritten

Pavel
  • 524
  • 4
  • 8
-1

Where are you setting up your bindings? Somewhere in your code you'll need to initialize the kernel with a ServiceModule like this:

_kernel = new StandardKernel(new YourNinjectModule());

And then in the module code:

public class YourNinjectModule: NinjectModule
{
    /// <summary>
    /// Loads the module into the kernel.
    /// </summary>
    public override void Load()
    {
        // ===========================================================
        //
        // Bind dependency injection.
        // Add entries in here for any new services or repositories.
        //
        // ===========================================================

        this.Bind<Icontract>().To<contract>();
    }
}
Garrett Vlieger
  • 9,354
  • 4
  • 32
  • 44
  • I am aware of this. The binding are configured correctly. The service works as expected. The discovery does not however. – Simon Halsey Jul 08 '12 at 00:36
  • I ask because I'm curious what your bindings are. You're requesting the concrete class (`contract`) versus the interface (`Icontract`). Normally you would use `Get`. – Garrett Vlieger Jul 08 '12 at 14:55
  • Normally you would. However, ServiceHost & therefore NinjectServiceHost only accept concrete classes. If you specify `Icontract` when you call the factory method you get an error to that effect. – Simon Halsey Jul 09 '12 at 16:27