Quando você possui múltiplos endpoints para expor um serviço, na maioria das vezes, esses endpoints possuem características diferentes, pois você poderá publicá-lo através de HTTP para consumo externo, enquanto as aplicações locais, consomem este mesmo serviço através de TCP, para uma melhor performance.
A configuração abaixo ilustra a exposição de um mesmo serviço e de um mesmo contrato através dos protocolos TCP e HTTP. Cada um dos protocolos possuem características diferentes de comunicação, e justamente por isso, exigem bindings diferentes.
<system.serviceModel>
<services>
<service name=”App.Servico”>
<host>
<baseAddresses>
<add baseAddress=”net.tcp://localhost:9838″/>
<add baseAddress=”http://localhost:8478″/>
</baseAddresses>
</host>
<endpoint address=”srv”
contract=”App.IContrato1″
binding=”netTcpBinding”/>
<endpoint address=”srv”
contract=”App.IContrato1″
binding=”basicHttpBinding”/>
</service>
</services>
</system.serviceModel>
Cada endpoint é composto por um endereço, binding e contrato, e cada endpoint possui seu próprio listener e channel stack, que varia de acordo com o binding escolhido. Em algumas situações, é comum ter mais do que um contrato para o mesmo serviço, onde queremos compartilhar o mesmo endereço para ambos contratos. Abaixo podemos ver um serviço que tem esse comportamento:
<system.serviceModel>
<services>
<service name=”App.Servico”>
<host>
<baseAddresses>
<add baseAddress=”net.tcp://localhost:9838″/>
</baseAddresses>
</host>
<endpoint address=”srv”
contract=”App.IContrato1″
binding=”netTcpBinding”/>
<endpoint address=”srv”
contract=”App.IContrato2″
binding=”netTcpBinding”/>
</service>
</services>
</system.serviceModel>
Repare que temos dois contratos (IContrato1 e IContrato2) expostos através de TCP e usando o mesmo endereço. Isso somente é possível porque o WCF reutiliza a mesma instância do binding para efetuar a comunicação, e difere a execução baseando-se nas Soap Actions. Se cada binding tiver sua configuração específica (definido através do atributo bindingConfiguration), então isso fará com que o WCF crie instâncias diferentes do mesmo binding, resultando em uma exceção tipo do InvalidOperationException sendo disparada, informando que não é permitido associar uma mesma instância binding à endereços diferentes.
Se você tiver endereços distintos, então duas instâncias distintas do binding correspondente serão criadas para atender cada um deles. Esse mesmo cuidado você precisa ter ao configurar o serviço de forma imperativa. Ao chamar o método AddServiceEndpoint da classe ServiceHost, você deverá se preocupar em passar a mesma instância do binding, como por exemplo:
using (ServiceHost host =
new ServiceHost(typeof(Servico), new Uri[] { new Uri(“net.tcp://localhost:9838”) }))
{
NetTcpBinding b = new NetTcpBinding();
host.AddServiceEndpoint(typeof(IContrato1), b, “srv”);
host.AddServiceEndpoint(typeof(IContrato2), b, “srv”);
host.Open();
Console.ReadLine();
}