Configuração e suporte de metadados

Este tópico descreve como habilitar o suporte à configuração e a metadados para associações e elementos de associação.

Visão Geral de Configuração e Metadados

Este tópico discute as tarefas a seguir, que são os itens opcionais 1, 2 e 4 na lista de tarefas Desenvolvimento de Canais.

  • Como habilitar o suporte a arquivos de configuração para um elemento de associação.

  • Como habilitar o suporte a arquivos de configuração para uma associação.

  • Exportação do WSDL e das declarações de política para um elemento de associação.

  • Identificação do WSDL e das declarações de política para inserir e configurar a associação ou o elemento de associação.

Para obter informações sobre como criar associações definidas pelo usuário e elementos de associação, confira Criação de associações definidas pelo usuário e Criação de elemento de associação, respectivamente.

Adição de Suporte à Configuração

Para habilitar o suporte a arquivos de configuração para um canal, você deve implementar duas seções de configuração, System.ServiceModel.Configuration.BindingElementExtensionElement, que permite o suporte à configuração para elementos de associação, e o System.ServiceModel.Configuration.StandardBindingElement e o System.ServiceModel.Configuration.StandardBindingCollectionElement<TStandardBinding,TBindingConfiguration>, que permitem o suporte à configuração para associações.

Uma maneira mais fácil de fazer isso é usar a ferramenta de exemplo ConfigurationCodeGenerator para gerar o código de configuração para associações e elementos de associação.

Extensão do BindingElementExtensionElement

O código de exemplo a seguir é obtido do exemplo Transport: UDP. A UdpTransportElement é uma BindingElementExtensionElement que expõe UdpTransportBindingElement ao sistema de configuração. Com algumas substituições básicas, o exemplo define o nome da seção de configuração, o tipo do elemento de associação e como criar o elemento de associação. Os usuários podem registrar a seção de extensão em um arquivo de configuração da seguinte maneira.

<configuration>  
  <system.serviceModel>  
    <extensions>  
      <bindingElementExtensions>  
      <add name="udpTransport" type="Microsoft.ServiceModel.Samples.UdpTransportElement, UdpTransport" />  
      </bindingElementExtensions>  
    </extensions>  
  </system.serviceModel>  
</configuration>  

A extensão pode ser referenciada em associações personalizadas para usar o UDP como o transporte.

<configuration>  
  <system.serviceModel>  
    <bindings>  
      <customBinding>  
       <binding configurationName="UdpCustomBinding">  
         <udpTransport/>  
       </binding>  
      </customBinding>  
    </bindings>  
  </system.serviceModel>  
</configuration>  

Adição de Configuração para uma Associação

A seção SampleProfileUdpBindingCollectionElement é uma StandardBindingCollectionElement<TStandardBinding,TBindingConfiguration> que expõe SampleProfileUdpBinding ao sistema de configuração. A maior parte da implementação é delegada ao SampleProfileUdpBindingConfigurationElement, que deriva do StandardBindingElement. O SampleProfileUdpBindingConfigurationElement tem propriedades que correspondem às propriedades em SampleProfileUdpBinding e funções a serem mapeadas a partir da associação ConfigurationElement. Por fim, o método OnApplyConfiguration é substituído no SampleProfileUdpBinding, conforme mostrado no código de exemplo a seguir.

protected override void OnApplyConfiguration(string configurationName)  
{  
            if (binding == null)  
                throw new ArgumentNullException("binding");  
  
            if (binding.GetType() != typeof(SampleProfileUdpBinding))  
            {  
                var expectedType = typeof(SampleProfileUdpBinding).AssemblyQualifiedName;
                var typePassedIn = binding.GetType().AssemblyQualifiedName;
                throw new ArgumentException($"Invalid type for binding. Expected type: {expectedType}. Type passed in: {typePassedIn}.");  
            }  
            SampleProfileUdpBinding udpBinding = (SampleProfileUdpBinding)binding;  
  
            udpBinding.OrderedSession = this.OrderedSession;  
            udpBinding.ReliableSessionEnabled = this.ReliableSessionEnabled;  
            udpBinding.SessionInactivityTimeout = this.SessionInactivityTimeout;  
            if (this.ClientBaseAddress != null)  
                   udpBinding.ClientBaseAddress = ClientBaseAddress;  
}  

Para registrar esse manipulador com o sistema de configuração, adicione a seção a seguir ao arquivo de configuração relevante.

<configuration>  
  <configSections>  
     <sectionGroup name="system.serviceModel">  
         <sectionGroup name="bindings">  
                 <section name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport" />  
         </sectionGroup>  
     </sectionGroup>  
  </configSections>  
</configuration>  

Então, ele poderá ser referenciado na seção de configuração <system.serviceModel>.

<configuration>  
  <system.serviceModel>  
    <client>  
      <endpoint configurationName="calculator"  
                address="soap.udp://localhost:8001/"
                bindingConfiguration="CalculatorServer"  
                binding="sampleProfileUdpBinding"
                contract= "Microsoft.ServiceModel.Samples.ICalculatorContract">  
      </endpoint>  
    </client>  
  </system.serviceModel>  
</configuration>  

Adição de Suporte a Metadados para um Elemento de Associação

Para integrar um canal ao sistema de metadados, ele deve permitir a importação e a exportação de política. Isso permite que ferramentas, como a ServiceModel Metadata Utility Tool (Svcutil.exe), gerem os clientes do elemento de associação.

Adição de Suporte a WSDL

O elemento de associação de transporte em uma associação é responsável por exportar e importar as informações de endereçamento em metadados. Ao usar uma associação SOAP, o elemento de associação de transporte também deve exportar um URI de transporte correto em metadados. O código de exemplo a seguir é obtido do exemplo Transport: UDP.

Exportação do WSDL

Para exportar as informações de endereçamento, o UdpTransportBindingElement implementa a interface System.ServiceModel.Description.IWsdlExportExtension. O método IWsdlExportExtension.ExportEndpoint adiciona as informações de endereçamento corretas à porta WSDL.

if (context.WsdlPort != null)  
{  
    AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);  
}  

A implementação UdpTransportBindingElement do método ExportEndpoint também exporta um URI de transporte, quando o ponto de extremidade usa uma associação SOAP:

WsdlNS.SoapBinding soapBinding = GetSoapBinding(context, exporter);  
if (soapBinding != null)  
{  
    soapBinding.Transport = UdpPolicyStrings.UdpNamespace;  
}  

Importação do WSDL

Para estender o sistema de importação do WSDL para lidar com a importação dos endereços, adicione a seguinte configuração ao arquivo de configuração para Svcutil.exe, conforme mostrado no arquivo de Svcutil.exe.config:

<configuration>  
  <system.serviceModel>  
    <client>  
      <metadata>  
        <wsdlImporters>  
          <extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />  
        </wsdlImporters>  
      </metadata>  
    </client>  
  </system.serviceModel>  
</configuration>  

Ao executar Svcutil.exe, há duas opções para fazer com que Svcutil.exe carregue as extensões de importação do WSDL:

  1. Aponte o Svcutil.exe para o arquivo de configuração usando o /SvcutilConfig:<file>.

  2. Adicione a seção de configuração a Svcutil.exe.config no mesmo diretório que Svcutil.exe.

O tipo UdpBindingElementImporter implementa a interface System.ServiceModel.Description.IWsdlImportExtension. O método ImportEndpoint importa o endereço da porta WSDL:

BindingElementCollection bindingElements = context.Endpoint.Binding.CreateBindingElements();  
TransportBindingElement transportBindingElement = bindingElements.Find<TransportBindingElement>();  
if (transportBindingElement is UdpTransportBindingElement)  
{  
    ImportAddress(context);  
}  

Adição de suporte a políticas

O elemento de associação personalizada pode exportar declarações de política na associação WSDL para um ponto de extremidade de serviço, para expressar os recursos desse elemento de associação. O código de exemplo a seguir é obtido do exemplo Transport: UDP.

Exportação de Política

O tipo UdpTransportBindingElement implementa System.ServiceModel.Description.IPolicyExportExtension para adicionar suporte à política de exportação. Como resultado, System.ServiceModel.Description.MetadataExporter inclui UdpTransportBindingElement na geração de política para qualquer associação que o inclua.

Em IPolicyExportExtension.ExportPolicy, adicione uma declaração para UDP e outra declaração se o canal estiver no modo multicast. Isso ocorre porque o modo multicast afeta a forma como a pilha de comunicação é construída e, portanto, deve ser coordenado entre ambos os lados.

ICollection<XmlElement> bindingAssertions = context.GetBindingAssertions();  
XmlDocument xmlDocument = new XmlDocument();  
bindingAssertions.Add(xmlDocument.CreateElement(  
UdpPolicyStrings.Prefix, UdpPolicyStrings.TransportAssertion, UdpPolicyStrings.UdpNamespace));  
if (Multicast)  
{  
    bindingAssertions.Add(xmlDocument.CreateElement(  
UdpPolicyStrings.Prefix, UdpPolicyStrings.MulticastAssertion,     UdpPolicyStrings.UdpNamespace));  
}  

Como os elementos de associação de transporte personalizada são responsáveis por lidar com o endereçamento, a implementação System.ServiceModel.Description.IPolicyExportExtension no UdpTransportBindingElement também deve lidar com a exportação das devidas declarações de política de WS-Addressing, para indicar a versão do WS-Addressing usado.

AddWSAddressingAssertion(context, encodingBindingElement.MessageVersion.Addressing);  

Importação de Política

Para estender o sistema de importação de política, adicione a seguinte configuração ao arquivo de configuração para Svcutil.exe, conforme mostrado no arquivo de Svcutil.exe.config:

<configuration>  
  <system.serviceModel>  
    <client>  
      <metadata>  
        <policyImporters>  
          <extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />  
        </policyImporters>  
      </metadata>  
    </client>  
  </system.serviceModel>  
</configuration>  

Em seguida, implemente System.ServiceModel.Description.IPolicyImportExtension por meio de nossa classe registrada (UdpBindingElementImporter). Em IPolicyImportExtension.ImportPolicy, examine as declarações no namespace apropriado e as processe para gerar o transporte e verificar se é multicast. Além disso, remova as declarações que o importador trata na lista de declarações de associação. Novamente, ao executar Svcutil.exe, há duas opções para integração:

  1. Aponte o Svcutil.exe para o nosso arquivo de configuração usando o /SvcutilConfig:<file>.

  2. Adicione a seção de configuração a Svcutil.exe.config no mesmo diretório que Svcutil.exe.

Adição de um Importador de Associação Padrão Personalizada

O Svcutil.exe e o tipo System.ServiceModel.Description.WsdlImporter, por padrão, reconhecem e importam as associações fornecidas pelo sistema. Caso contrário, a associação será importada como instância System.ServiceModel.Channels.CustomBinding. Para habilitar o Svcutil.exe e o WsdlImporter para importar o SampleProfileUdpBinding, o UdpBindingElementImporter também atua como importador de associação padrão personalizada.

Um importador de associação padrão personalizada implementa o método ImportEndpoint na interface System.ServiceModel.Description.IWsdlImportExtension para examinar a instância System.ServiceModel.Channels.CustomBinding importada dos metadados, para ver se ela poderia ter sido gerada por uma associação padrão específica.

if (context.Endpoint.Binding is CustomBinding)  
{  
    Binding binding;  
    if (transportBindingElement is UdpTransportBindingElement)  
    {  
        //if TryCreate is true, the CustomBinding will be replace by a SampleProfileUdpBinding in the  
        //generated config file for better typed generation.  
        if (SampleProfileUdpBinding.TryCreate(bindingElements, out binding))  
        {  
            binding.Name = context.Endpoint.Binding.Name;  
            binding.Namespace = context.Endpoint.Binding.Namespace;  
            context.Endpoint.Binding = binding;  
        }  
    }  
}  

Em geral, a implementação de um importador de associação padrão personalizada envolve verificar as propriedades dos elementos de associação importados, para ver se apenas as propriedades que poderiam ter sido definidas pela associação padrão foram alteradas e se todas as outras propriedades são os padrões. Uma estratégia básica para implementar um importador de associação padrão é criar uma instância da associação padrão, propagar as propriedades dos elementos de associação para a instância de associação padrão compatível com a associação padrão e comparar os elementos de associação da associação padrão com os elementos de associação importados.