7

I have a WCF service (.NET 4) that exposes 4 endpoints of which one endpoint is configured with protobuf-net (V1.0.0.280) behavior extension. However, I noticed that protobuf-net behavior kicks in for ALL defined endpoints including the ones protbuf-net is not configured for! I have pasted my config below. Am I missing something? Any help is greatly appreciated .. thx

    <service name="MyService" behaviorConfiguration="MyServiceBehavior">
    <endpoint address="Http.Basic" binding="basicHttpBinding" bindingConfiguration="Http.Basic.Config" contract="IMyService" behaviorConfiguration="DefaultBehavior" />
    <endpoint address="Http.Binary" binding="customBinding" bindingConfiguration="Http.Binary.Config" contract="IMyService" behaviorConfiguration="DefaultBehavior" />
    <endpoint address="Tcp.Binary" binding="customBinding" bindingConfiguration="Tcp.Binary.Config" contract="IMyService" behaviorConfiguration="DefaultBehavior" />
    <endpoint address="Http.ProtoBuf" binding="basicHttpBinding" bindingConfiguration="Http.Basic.Config" contract="IMyService" behaviorConfiguration="ProtoBufBehavior" />
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8085/MyService"/>
        <add baseAddress="net.tcp://localhost:8086/MyService"/>
      </baseAddresses>
    </host>
  </service>

  <behaviors>
    <serviceBehaviors>
      <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior name="DefaultBehavior">
        <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      </behavior>
      <behavior name="ProtoBufBehavior">
        <ProtoBufSerialization />
      </behavior>
    </endpointBehaviors>
  </behaviors>

  <bindings>
    <basicHttpBinding>
      <binding name="Http.Basic.Config" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
      </binding>
    </basicHttpBinding>
    <customBinding>
      <binding name="Http.Binary.Config" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00">
        <binaryMessageEncoding />
        <httpTransport allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" />
      </binding>
      <binding name="Tcp.Binary.Config" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00">
        <binaryMessageEncoding />
        <tcpTransport hostNameComparisonMode="StrongWildcard" />
      </binding>
    </customBinding>
  </bindings>
Japps
  • 71
  • 1
  • 2

1 Answers1

1

That is odd, but (checks the code) I only ever apply changes within an endpoint supplied to me by WCF:

    void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
        ReplaceDataContractSerializerOperationBehavior(endpoint);
    }

    void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        ReplaceDataContractSerializerOperationBehavior(endpoint);
    }

    private static void ReplaceDataContractSerializerOperationBehavior(ServiceEndpoint serviceEndpoint)
    {
        foreach (OperationDescription operationDescription in serviceEndpoint.Contract.Operations)
        {
            ReplaceDataContractSerializerOperationBehavior(operationDescription);
        }
    }


    private static void ReplaceDataContractSerializerOperationBehavior(OperationDescription description)
    {
        DataContractSerializerOperationBehavior dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        if (dcsOperationBehavior != null)
        {
            description.Behaviors.Remove(dcsOperationBehavior);
            description.Behaviors.Add(new ProtoOperationBehavior(description));
        }
    }

i.e. "given an endpoint (by WCF), loop over each operation (method) in that endpoint, and change the serializer from DCS to PB"

This raises the intriguing possibility that the contract definitions (and hence the operation definitions) are themselves shared between all the endpoints - but I am honestly not sure about that. If that is the case, I don't see that it would ever be possible to have different processors per endpoint. I am not, however, a WCF-guru. This is... perplexing.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    Many thanks for your super quick response and I do see your point. I noticed something really strange while playing around this, which is, if I keep the endpoint with protobuf behavior as the last node in config then everything works fine as expected.. However, if I move it to the first position then all endpoints pick up protobuf. If I move it in between then the endpoints defined after it picks up protobuf !! Will dig deeper and post if I find the root cause – Japps Aug 12 '11 at 06:53
  • As i understood, contractDescription is shared between endpoints, indeed. But i don't understand why proto-behaviour is added only to endpoints defined after endpoint with proto-behaviuor (including endpoint for which behaviour is configured explicitly). We use the similar solution as @Japps: add endpoint with proto as last endpoint to the host – Ruslan Mar 12 '14 at 12:16
  • This old post was the first link google offered when I searched for this problem. But I get this behaviour on the client side. I'm applying the protocol behaviour programatically to the endpoint that needs this config. But am seeing the same behaviour as @Japps mentioned. – Akhilesh Apr 26 '22 at 05:43