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.

Request-Reply
Figura 1. Request-Reply

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.

One-Way
Figura 2. One-Way

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.

Duplex
Figura 3. Duplex

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.