Formatador de operação e seletor de operação

O exemplo QueryStringFormatter demonstra como os pontos de extensibilidade do Windows Communication Foundation (WCF) podem ser usados para permitir dados de mensagem em um formato diferente do que o WCF espera. Por padrão, os formatadores WCF esperam que os parâmetros do método sejam incluídos no soap:body elemento. A amostra mostra como implementar um formatador de operação personalizado que analisa dados de parâmetro de uma string de consulta HTTP GET e invoca métodos usando esses dados.

O exemplo baseia-se na Introdução, que implementa o contrato de serviço ICalculator. Ele mostra como as mensagens Adicionar, Subtrair, Multiplicar e Dividir podem ser alteradas para usar HTTP GET para solicitações de cliente para servidor e HTTP POST com mensagens POX para respostas de servidor para cliente.

Para fazer isso, o exemplo fornece o seguinte:

  • QueryStringFormatter, que implementa IClientMessageFormatter e IDispatchMessageFormatter para o cliente e o servidor, respectivamente, e processa os dados na cadeia de caracteres de consulta.

  • UriOperationSelector, que implementa IDispatchOperationSelector no servidor para executar a expedição de operação com base no nome da operação na solicitação GET.

  • EnableHttpGetRequestsBehavior comportamento do terminal (e configuração correspondente), que adiciona o seletor de operação necessário ao tempo de execução.

  • Mostra como inserir um novo formatador de operação no runtime.

  • Neste exemplo, o cliente e o serviço são programas de console (.exe).

Observação

O procedimento de instalação e as instruções de compilação dessa amostra estão no final deste tópico.

Conceitos Principais

QueryStringFormatter - O formatador de operação é o componente no WCF responsável por converter uma mensagem em uma matriz de objetos de parâmetro e uma matriz de objetos de parâmetro em uma mensagem. Isso é feito no cliente usando a IClientMessageFormatterinterface e no servidor com a IDispatchMessageFormatterinterface. Essas interfaces permitem que os usuários obtenham as mensagens de solicitação e resposta dos métodos Serialize e Deserialize.

Neste exemplo, QueryStringFormatter implementa essas duas interfaces e é implementado no cliente e no servidor.

Solicitação:

  • O exemplo usa a TypeConverter classe para converter dados de parâmetro na mensagem de solicitação de e para cadeias de caracteres. Se um TypeConverter não estiver disponível para um tipo específico, o formatador de exemplo gerará uma exceção.

  • IClientMessageFormatter.SerializeRequest No método no cliente, o formatador cria um URI com o endereço Apropriado para endereçar e acrescenta o nome da operação como um sufixo. Esse nome é usado para expedir para a operação apropriada no servidor. Em seguida, ele usa a matriz de objetos de parâmetro e serializa os dados de parâmetro para a cadeia de caracteres de consulta URI usando nomes de parâmetro e os valores convertidos pela TypeConverter classe. As propriedades To e Via estão definidas para esse valor. MessageProperties é acessado através da Properties propriedade.

  • No IDispatchMessageFormatter.DeserializeRequest método no servidor, o formatador recupera o Via URI nas propriedades da mensagem de solicitação recebida. Ele analisa os pares nome-valor na string de consulta do URI em nomes e valores de parâmetros e usa os nomes e valores de parâmetros para preencher a matriz de parâmetros passados para o método. Observe que o despacho da operação já ocorreu, portanto, o sufixo do nome da operação é ignorado neste método.

Resposta:

  • Neste exemplo, HTTP GET é usado apenas para a solicitação. O formatador delega o envio da resposta ao formatador original que teria sido usado para gerar uma mensagem XML. Uma das metas deste exemplo é mostrar como esse formatador de delegação pode ser implementado.

UriPathSuffixOperationSelector Class

A IDispatchOperationSelector interface permite que os usuários implementem sua própria lógica para a qual a operação uma mensagem específica deve ser enviada.

Neste exemplo, UriPathSuffixOperationSelector deve ser implementado no servidor para selecionar a operação apropriada porque o nome da operação está incluído no URI HTTP GET em vez de um cabeçalho de ação na mensagem. O exemplo é configurado para permitir apenas nomes de operação que não diferenciam maiúsculas de minúsculas.

O SelectOperation método usa a mensagem de entrada e pesquisa o Via URI em suas propriedades de mensagem. Ele extrai o sufixo do nome da operação do URI, consulta uma tabela interna para obter o nome da operação para a qual a mensagem deve ser despachada e retorna esse nome de operação.

EnableHttpGetRequestsBehavior Class

O UriPathSuffixOperationSelector componente pode ser configurado programaticamente ou por meio de um comportamento de ponto de extremidade. O exemplo implementa o EnableHttpGetRequestsBehavior comportamento, que é especificado no arquivo de configuração de aplicativo do serviço.

No servidor:

O OperationSelector é definido para a IDispatchOperationSelector implementação.

Por padrão, o WCF usa um filtro de endereço de correspondência exata. O URI na mensagem de entrada contém um sufixo de nome de operação seguido por uma cadeia de caracteres de consulta que contém dados de parâmetro, portanto, o comportamento do ponto de extremidade também altera o filtro de endereço para ser um filtro de correspondência de prefixo. Ele usa o WCFPrefixEndpointAddressMessageFilter para essa finalidade.

Instalando formatadores de operação

Os comportamentos de operação que especificam formatadores são exclusivos. Um desses comportamentos é sempre implementado por padrão para cada operação para criar o formatador de operação necessário. No entanto, esses comportamentos se parecem apenas com outro comportamento de operação; eles não são identificáveis por nenhum outro atributo. Para instalar um comportamento de substituição, a implementação deve procurar comportamentos de formatador específicos que são instalados pelo carregador de tipo WCF por padrão e substituí-lo ou adicionar um comportamento compatível para ser executado após o comportamento padrão.

Esses comportamentos de formatadores de operação podem ser configurados programaticamente antes da chamada CommunicationObject.Open ou especificando um comportamento de operação que é executado após o padrão. No entanto, ele não pode ser facilmente configurado por um comportamento de terminal (e, portanto, por configuração) porque o modelo de comportamento não permite que um comportamento substitua outros comportamentos ou modifique a árvore de descrição.

No cliente:

A IClientMessageFormatter implementação deve ser implementada para que possa converter as solicitações em solicitações HTTP GET e delegar ao formatador original para respostas. Isso é feito chamando o EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior método auxiliar.

Isso deve ser feito antes de ligar CreateChannel.

void ReplaceFormatterBehavior(OperationDescription operationDescription, EndpointAddress address)
{
    // Remove the DataContract behavior if it is present.
    IOperationBehavior formatterBehavior = operationDescription.Behaviors.Remove<DataContractSerializerOperationBehavior>();
    if (formatterBehavior == null)
    {
        // Remove the XmlSerializer behavior if it is present.
        formatterBehavior = operationDescription.Behaviors.Remove<XmlSerializerOperationBehavior>();
        ...
    }

    // Remember what the innerFormatterBehavior was.
    DelegatingFormatterBehavior delegatingFormatterBehavior = new DelegatingFormatterBehavior(address);
    delegatingFormatterBehavior.InnerFormatterBehavior = formatterBehavior;
   operationDescription.Behaviors.Add(delegatingFormatterBehavior);
}

No servidor:

  • A IDispatchMessageFormatter interface deve ser implementada para que possa ler solicitações HTTP GET e delegar ao formatador original para escrever respostas. Isso é feito chamando o mesmo EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior método auxiliar que o cliente (consulte o exemplo de código anterior).

  • Isso deve ser feito antes de Open ser chamado. Neste exemplo, mostramos como o formatador é modificado manualmente antes de chamar Open. Outra maneira de conseguir a mesma coisa é derivar uma classe de ServiceHost que faz as chamadas EnableHttpGetRequestsBehavior.ReplaceFormatterBehavior antes de abrir (consulte a documentação de hospedagem e exemplos para obter exemplos).

Experiência do usuário

No servidor:

  • A implementação do servidor ICalculator não precisa ser alterada.

  • O App.config para o serviço deve usar uma associação POX personalizada que define o messageVersion atributo do textMessageEncoding elemento como None.

    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding messageVersion="None" />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
    
  • O App.config para o serviço também deve especificar o personalizado EnableHttpGetRequestsBehavior adicionando-o à seção extensões de comportamento e usando-o.

    <behaviors>
      <endpointBehaviors>
        <behavior name="enableHttpGetRequestsBehavior">
          <enableHttpGetRequests />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    
    <extensions>
      <behaviorExtensions>
        <!-- Enabling HTTP GET requests: Behavior Extension -->
        <add
          name="enableHttpGetRequests"           type="Microsoft.ServiceModel.Samples.EnableHttpGetRequestsBehaviorElement, QueryStringFormatter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
    
  • Adicionar formatores de operação antes de chamar Open.

No cliente:

  • A implementação do cliente não precisa ser alterada.

  • O App.config para o serviço deve usar uma associação POX personalizada que define o messageVersion atributo do textMessageEncoding elemento como None. Uma diferença do serviço é que o cliente deve habilitar o endereçamento manual para que o endereço de saída possa ser modificado.

    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding messageVersion="None" />
          <httpTransport manualAddressing="True" />
        </binding>
      </customBinding>
    </bindings>
    
  • O App.config para o cliente deve especificar o mesmo personalizado EnableHttpGetRequestsBehavior que o servidor.

  • Adicionar formatores de operação antes de chamar CreateChannel().

Quando você executa a amostra, as solicitações de operação e as respostas são exibidas na janela do console do cliente. Todas as quatro operações (Adicionar, Subtrair, Multiplicar e Dividir) devem ter êxito.

Para configurar, compilar, e executar o exemplo
  1. Verifique se você executou o Procedimento de instalação única para os exemplos do Windows Communication Foundation.

  2. Para compilar a solução, siga as instruções contidas em Como compilar as amostras do Windows Communication Foundation.

  3. Para executar a amostra em uma configuração de computador único ou entre computadores, siga as instruções contidas em Como executar as amostras do Windows Communication Foundation.