1

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.

delux
  • 1,694
  • 10
  • 33
  • 64
  • Was demoQueryServiceHttpBinding supposed to be demoServiceHttpBinding? – Joel McBeth Sep 10 '16 at 17:10
  • Could you post how you are calling into the service from the client? – Joel McBeth Sep 10 '16 at 17:29
  • @jcmcbeth I have renamed demoQueryServiceHttpBinding into demoServiceHttpBinding. This was just a syntax error while I was writing the question. The main issue still remains. Also I have updated the question with more code (in Edit 1) related to the way of calling the service. – delux Sep 12 '16 at 10:16

1 Answers1

1

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.

Igor Labutin
  • 1,406
  • 10
  • 10
  • I did some changes in Web.config: I removed the endpoint "BasicHttpExampleAddress" and that solved my problem. Also I have renamed the "mex" end point into "mextcp". So this solved my problem for now, but what if I want to have "basicHttpBining" as well here. Is it possible to have different end points: "basicHttpBining" (without callback) and "netTcpBinding" (with callback) at the same time? – delux Sep 12 '16 at 16:54
  • 1
    You will have to use two different contracts. Because contract defines what operations clients can perform. And if contract says that it has a callback, then client should be able to use callback no matter how it connects to the service. If your service also have another way of functioning (i.e. without callbacks), then define one more contract which does not use `ServiceCallbackAttribute` and implement another service class. Then you will be able to expose it via basicHttp endpoint. Your two services can still use same 'backend' internally for operations. – Igor Labutin Sep 14 '16 at 08:07