O WCF faz a sua comunicação entre serviço, e esses serviços fazem a troca de mensagens entre client e services, podendo ter mais de uma direção.
A forma de como essas mensagens é transportada é o que iremos falar nesse artigo.
Quando for fazer uma requisição do meu cliente para o meu serviço, uma mensagem é enviada via Proxy, o caminho pode ser feita via HTTP ou TCP, dependo do meu protocolo, a mensagem é envelopada atrás do Protocolo SOAP.
Existem três tipos de mensagens no WCF: Request-Reply, One-Way e Duplex.
O tipo de mensagem padrão é o Request-Reply(Requisição Resposta).
Request-Reply
Quando essa mensagem chega ao meu Serviço, através do Proxy, ela faz todo o procedimento necessário, após ter terminado e já contendo a resposta, ela devolve outra mensagem SOAP, contendo o resultado do processamento, para o cliente que a requisitou. Essa operação é feita de forma sincrônica, ou seja, enquanto não tiver o retorno do meu serviço à aplicação fica indisponível, como mostra a Figura 1.

One-Way
Quando uma mensagem é enviada para o meu serviço, ela não ira esperar nenhum retorno do meu serviço, e nem um possível erro, após essa mensagem ter chegado ao meu serviço a aplicação já esta disponível, pois não tem o retorno, se houver uma quantidade de requisição ao meu serviço essa mensagem fica aguardando a chegado enquanto isso a aplicação fica indisponível, como mostra a Figura 2.

Todos os Bindings suportar esse tipo de mensagem.
Para definirmos uma mensagem como do tipo One-Way, devemos definir a propriedade IsOneWay como true, fornecido pelo atributo OperationContractAttribute.
O método que estiver decorado com atributo IsOneWay como true, deverá ser um método void como obrigatório.
[ServiceContract]
public interface IMensagem
{
[OperationContract(IsOneWay=true)]
void SalvarDados(Dados dados);
}
Algumas observações devem ser mencionadas, para que o Proxy do cliente não seja afetado pelo retorno, como o serviço estiver configurado como Percall (não mantem estado), e com os binding BasicHttpBinding ou WSHttpBinding, sem as opções de segurança e mensagens confiáveis habilitadas.
Duplex
A direção das mensagens é bidirecional, então eu posso mandar uma mensagem para o meu serviço e minha aplicação fica disponível e depois em qualquer momento o meu serviço poderá mandar uma mensagem de retorno, um callback, ou seja, alem do meu cliente se comunicar com o meu serviço, o meu serviço também se comunica com o cliente, como mostra a Figura 3.

Os bindings NetTcpBinding e NetNamedPipeBinding fazem isso nativamente por causa de seus protocolos.
O Protocolo HTTP não fornece esse suporte, pois sua natureza não tem a ligação do cliente ao servidor, para que callback funcione nesse tipo de protocolo, foi inventado o binding WSDualHttpBinding. Quando implementado esse tipo bindind, o WCF utilizará um canal diferente para invocar um callback.
Para efetuar o callback é necessário uma interface de callback (um contrato de callback), essa interface não há necessidade de decorar com o atributo ServiceContract, e os parâmetros alem de decorar como o atributo OperationContract, é uma boa pratica informar que ele seja One-Way, isso é necessário para evitar um possível deadlocks, no meu contrato de serviço é necessário informar ao parâmetro CallbackContract a minha interface de callback.
//Interface de callback
public interface ICallback
{
[OperationContract(IsOneWay=true)]
void ClienteSendoNotificado();
}
//Interface de Serviço (Contrato de Serviço)
[ServiceContract(CallbackContract= typeof(ICallback))]
public interface IMensagem
{
[OperationContract]
void Notificar();
}
Quem determina quem ira executar o callback, será o serviço, ele precisa de um canal de comunicação entre o serviço e o cliente e para isso dentro da classe OperationContext existe um método genérico GetCallbackChannel, que retorna uma instancia do canal de comunicação entre o cliente e serviço, e se o valor for diferente de null, significa que o cliente implementou o contrato de callback
Quanto for trabalhar com retorno de callback no nosso Proxy(Cliente) é necessário passar qual classe ira ter o método de callback no construtor do Proxy.
using (Mensagem.MensagemClient proxy =
new Mensagem.MensagemClient( new InstanceContext
(new Retorno()),"NetTcpBinding_IMensagem"))
{
Console.WriteLine(proxy.MensagemBoasVindas());
Console.ReadKey();
}
public class Retorno:ICallback
{
public void ClienteSendoNotificado()
{
throw new NotImplementedException();
}
}
Nem todos os binding suportam callback. Na chamada do meu serviço, o tipo das mensagens, não interfere no meu Proxy.
E para que o callback acione o meu método é necessário que a classe do Proxy ainda esteja ativa.