Criando associações definidas pelo usuário

Há várias maneiras de criar associações não fornecidas pelo sistema:

  • Crie uma associação personalizada, com base na classe CustomBinding, que é um contêiner que você preenche com elementos de associação. A associação personalizada é adicionada a um ponto de extremidade de serviço. Você pode criar a associação personalizada por meio de programação ou em um arquivo de configuração de aplicativo. Para usar um elemento de associação de um arquivo de configuração de aplicativo, o elemento de associação precisa estender BindingElementExtensionElement. Para obter mais informações sobre como criar associações personalizadas, confira Associações personalizadas e CustomBinding.

  • Você pode criar uma classe derivada de uma associação padrão. Por exemplo, você pode derivar uma classe de WSHttpBinding e substituir o método CreateBindingElements para obter os elementos de associação e inserir um elemento de associação personalizado ou estabelecer um valor específico para a segurança.

  • Você pode criar um tipo Binding para controlar completamente toda a implementação de associação.

A ordem dos elementos de associação

Cada elemento de associação representa uma etapa de processamento no envio ou no recebimento de mensagens. Em tempo de execução, os elementos de associação criam os canais e os ouvintes necessários para criar pilhas de canal de saída e de entrada.

Há três tipos principais de elementos de associação: elementos de associação de protocolo, elementos de associação de codificação e elementos de associação de transporte.

Elementos de associação de protocolo – Esses elementos representam etapas de processamento de nível superior que atuam em mensagens. Os canais e os ouvintes criados por esses elementos de associação podem adicionar, remover ou modificar o conteúdo da mensagem. Uma associação especificada pode ter um número arbitrário de elementos de associação de protocolo, cada um herdando de BindingElement. O WCF (Windows Communication Foundation) inclui vários elementos de associação de protocolo, incluindo o ReliableSessionBindingElement e o SymmetricSecurityBindingElement.

Elemento de associação de codificação – Esses elementos representam transformações entre uma mensagem e uma codificação pronta para transmissão pela rede. As associações típicas do WCF incluem exatamente um elemento de associação de codificação. Entre os exemplos de elementos de associação de codificação estão o MtomMessageEncodingBindingElement, o BinaryMessageEncodingBindingElement e o TextMessageEncodingBindingElement. Se um elemento de associação de codificação não for especificado para uma associação, uma codificação padrão será usada. O padrão será texto quando o transporte for HTTP, e binário, caso contrário.

Elemento de associação de transporte – Esses elementos representam a transmissão de uma mensagem de codificação em um protocolo de transporte. As associações típicas do WCF incluem exatamente um elemento de associação de transporte, que herda de TransportBindingElement. Entre os exemplos de elementos de associação de transporte estão o TcpTransportBindingElement, o HttpTransportBindingElement e o NamedPipeTransportBindingElement.

Ao criar associações, a ordem dos elementos de associação adicionados é importante. Sempre adicione elementos de associação na seguinte ordem:

Camada Opções Obrigatório
Fluxo de transação System.ServiceModel.Channels.TransactionFlowBindingElement Não
Confiabilidade System.ServiceModel.Channels.ReliableSessionBindingElement Não
Segurança System.ServiceModel.Channels.SecurityBindingElement No
Duplex composto System.ServiceModel.Channels.CompositeDuplexBindingElement Não
Codificação Texto, Binário, MTOM, Personalizado Sim*
Transport TCP, Pipes nomeados, HTTP, HTTPS, MSMQ, Personalizado Yes

*Como uma codificação é necessária para cada associação, se uma codificação não for especificada, o WCF adicionará uma codificação padrão. O padrão é Texto/XML para os transportes HTTP e HTTPS e Binário, caso contrário.

Como criar um elemento de associação

Além dos tipos derivados de BindingElement fornecidos pelo WCF, você pode criar seus elementos de associação. Isso permite personalizar a forma como a pilha de associações é criada e os componentes que entram nela criando seu BindingElement que pode ser composto com os outros tipos fornecidos pelo sistema na pilha.

Por exemplo, se você implementar um LoggingBindingElement que forneça a capacidade de registrar a mensagem em um banco de dados, coloque-a acima de um canal de transporte na pilha de canais. Nesse caso, o aplicativo cria uma associação personalizada que compôs o LoggingBindingElement com TcpTransportBindingElement, como no exemplo a seguir.

Binding customBinding = new CustomBinding(  
  new LoggingBindingElement(),
  new TcpTransportBindingElement()  
);  

A forma como você escreve o novo elemento de associação depende da funcionalidade exata dele. Um dos exemplos, Transporte: UDP, fornece uma descrição detalhada de como implementar um tipo de elemento de associação.

Como criar uma associação

Um elemento de associação criado pelo usuário pode ser usado de duas maneiras. A seção anterior ilustra a primeira maneira: por meio de uma associação personalizada. Uma associação personalizada permite que o usuário crie uma associação própria com base em um conjunto arbitrário de elementos de associação, incluindo os criados pelo usuário.

Se você usar a associação em mais de um aplicativo, crie uma associação própria e estenda a Binding. Isso evitará a criação manual de uma associação personalizada sempre que você quiser usá-la. Uma associação definida pelo usuário permite definir o comportamento da associação e incluir elementos de associação definidos pelo usuário. Além disso, ela é pré-empacotada: você não precisa recompilar a associação toda vez que a usar.

No mínimo, uma associação definida pelo usuário precisa implementar o método CreateBindingElements e a propriedade Scheme.

O método CreateBindingElements retorna um novo BindingElementCollection que contém os elementos de associação para a associação. A coleção é ordenada e deve conter os elementos de associação de protocolo primeiro, seguidos do elemento de associação de codificação, seguido do elemento de associação de transporte. Ao usar os elementos de associação fornecidos pelo sistema do WCF, você precisa seguir as regras de ordenação de elemento de associação especificadas em Associações personalizadas. Essa coleção nunca precisa referenciar objetos referenciados na classe de associação definida pelo usuário. Consequentemente, os autores da associação precisam retornar um Clone() da BindingElementCollection em cada chamada a CreateBindingElements.

A propriedade Scheme representa o esquema de URI para o protocolo de transporte em uso na associação. Por exemplo, a WSHttpBinding e a NetTcpBinding retornam "http" e "net.tcp" das respectivas propriedades Scheme.

Para ver a lista completa de métodos e propriedades opcionais para associações definidas pelo usuário, confira Binding.

Exemplo

Este exemplo implementa a associação de perfil em SampleProfileUdpBinding, que deriva de Binding. A SampleProfileUdpBinding contém até quatro elementos de associação: um UdpTransportBindingElement criado pelo usuário e três fornecidos pelo sistema, TextMessageEncodingBindingElement, CompositeDuplexBindingElement e ReliableSessionBindingElement.

public override BindingElementCollection CreateBindingElements()  
{
    BindingElementCollection bindingElements = new BindingElementCollection();  
    if (ReliableSessionEnabled)  
    {  
        bindingElements.Add(session);  
        bindingElements.Add(compositeDuplex);  
    }  
    bindingElements.Add(encoding);  
    bindingElements.Add(transport);  
    return bindingElements.Clone();  
}  

Restrições de segurança com os contratos duplex

Nem todos os elementos de associação são compatíveis entre si. Em particular, há algumas restrições em elementos de associação de segurança quando usados com os contratos duplex.

Segurança de processo único

Você pode implementar a segurança "de processo único", em que todas as credenciais de segurança necessárias são enviadas em uma só mensagem, definindo o atributo negotiateServiceCredential do elemento de configuração da <mensagem> como false.

A autenticação de processo único não funciona com os contratos duplex.

Para contratos de solicitação-resposta, a autenticação de processo único funcionará se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IRequestChannel ou IRequestSessionChannel.

Para contratos unidirecionais, a autenticação unidirecional funcionará se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IRequestChannel, IRequestSessionChannel, IOutputChannel ou IOutputSessionChannel.

Os tokens de contexto de segurança do modo de cookie não podem ser usados com os contratos duplex.

Para contratos de solicitação-resposta, os tokens de contexto de segurança do modo de cookie só funcionarão se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IRequestChannel ou IRequestSessionChannel.

Para contratos unidirecionais, os tokens de contexto de segurança do modo cookie funcionarão se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IRequestChannel ou IRequestSessionChannel.

Tokens de contexto de segurança do modo de sessão

O SCT do modo de sessão funcionará para contratos duplex se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IDuplexChannel ou IDuplexSessionChannel.

O SCT do modo de sessão funcionará para contratos de solicitação-resposta se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IDuplexChannel, IDuplexSessionChannel, IRequestChannel ou IRequestSessionChannel.

O SCT do modo de sessão funcionará para contratos unidirecionais se a pilha de associação abaixo do elemento de associação de segurança der suporte à criação de instâncias IDuplexChannel, IDuplexSessionChannel, IRequestChannel ou IRequestSessionChannel.

Como fazer a derivação de uma associação padrão

Em vez de criar uma classe de associação totalmente nova, talvez seja possível estender uma das associações existentes fornecidas pelo sistema. Assim como ocorre no caso anterior, você precisa substituir o método CreateBindingElements e a propriedade Scheme.

Confira também