Search code examples
wcfwcf-bindingnettcpbindingwcf-callbacksduplex-channel

WCF netTcpBinding issue: Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it


I'm trying to create a callback in WCF service. Service so far was using basicHttpBinding, so I want to add another end point for netTcpBinding. Service is already hosted in IIS. First It was hosted in IIS 6, but then I installed IIS 7.

So, I'm getting the following error:

The requested service, 'net.tcp://localhost:1801/MyServiceName.svc/NetTcpExampleAddress' could not be activated. See the server's diagnostic trace logs for more information.

When seeing the log, this is the message:

enter image description here

So the main error is:

Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.

Here are my config files:

My Web.config for the server:

<system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="demoServiceNetTcpBinding">
          <security mode="None"/>
        </binding>
      </netTcpBinding>
      <basicHttpBinding>
        <binding name="demoServiceHttpBinding" receiveTimeout="00:05:00" sendTimeout="00:05:00" maxReceivedMessageSize="2147483647">
          <security mode="None"/>
        </binding>        
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="MyServerName.MyServiceName">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:1801/MyServiceName.svc/"/>
            <add baseAddress="http://localhost:1800/MyServiceName.svc/"/>
          </baseAddresses> 
        </host>
    <endpoint 
        address="NetTcpExampleAddress" 
        binding="netTcpBinding" 
        bindingConfiguration="demoServiceNetTcpBinding" 
        contract="MyServerName.SharedContract.IMyServiceName"/>
    <endpoint 
        address="BasicHttpExampleAddress" 
        binding="basicHttpBinding" 
        bindingConfiguration="demoServiceHttpBinding" 
        contract="MyServerName.SharedContract.IMyServiceName"/>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

My App.config for the client:

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="demoServiceNetTcpBinding">
          <security mode="None"/>
        </binding>
      </netTcpBinding>
      <basicHttpBinding>
        <binding name="demoServiceHttpBinding" receiveTimeout="00:05:00" sendTimeout="00:05:00" maxReceivedMessageSize="2147483647">
          <security mode="None"/>
        </binding>        
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint name="NetTcpExampleName"
          address="net.tcp://localhost:1801/DicomQueryService.svc/NetTcpExampleAddress"
          bindingConfiguration ="demoServiceNetTcpBinding"
          contract="MyServerName.SharedContract.IMyServiceName"
          binding="netTcpBinding" />
      <endpoint name="BasicHttpExampleName"
          address="http://localhost:1800/MyServiceName.svc/BasicHttpExampleAddress"
          bindingConfiguration ="demoServiceHttpBinding"
          contract="MyServerName.SharedContract.IMyServiceName"
          binding="basicHttpBinding" />
    </client>
  </system.serviceModel>

Settings in my IIS:

enter image description here

enter image description here

If there are any other pieces of code that you need, please let me know and I'll update the question.

EDIT 1:

Here are more details from the code, of how I'm calling the service from the client (on client side):

public class MyCommandClass : IMyServiceCallback
{
    public MyCommandClass()
    {
        var ctx = new InstanceContext(new MyCommandClass());
        DuplexChannelFactory<MyServerName.SharedContract.IMyServiceName> channel = new DuplexChannelFactory<MyServerName.SharedContract.IMyServiceName>(ctx, "NetTcpExampleName");
        MyServerName.SharedContract.IMyServiceName clientProxy = channel.CreateChannel();
        clientProxy.MyFunction(); //debug point is comming here and then it throws the error
        clientProxy.ProcessReport();
        (clientProxy as IClientChannel).Close();
        channel.Close();
    }

    public void Progress(int percentageCompleted)
    {
        Console.WriteLine(percentageCompleted.ToString() + " % completed");
    }
}

where interfaces (on server side) are defined as:

[ServiceContract(CallbackContract = typeof(IMyServiceCallback))]
public interface IMyServiceName
{
    [OperationContract]
    void MyFunction();

    [OperationContract(IsOneWay = true)]
    void ProcessReport();
}

public interface IMyServiceCallback
{
    [OperationContract(IsOneWay = true)]
    void Progress(int percentageCompleted);    
}

and service (on server side) is defined as:

public class MyServiceName: IMyServiceName
{
    public void MyFunction()
    {
        //do something
    }

    public void ProcessReport()
    {
        //trigger the callback method
        for (int i = 1; i <= 100; i++)
        {
            Thread.Sleep(100);
            OperationContext.Current.GetCallbackChannel<IMyServiceCallback>().Progress(i);
        }
    }
}

My methods so far are just a demo. Once the error related to this question is fixed, then I'll start with developing the methods.


Solution

  • Your service contract requires duplex connection (you have ServiceCallback attribute). Therefore all endpoints that this service exposes must support duplex connection. Net.tcp does support it, but basicHttp does not, so you cannot use basicHttp with your service now.