Especificando um endereço de ponto de extremidade

Toda a comunicação com um serviço Windows Communication Foundation (WCF) ocorre por meio de seus pontos de extremidade. Cada ServiceEndpoint um contém um Address, um Bindinge um Contract. O contrato especifica quais operações estão disponíveis. A associação especifica como se comunicar com o serviço e o endereço especifica onde encontrar o serviço. Cada ponto de extremidade deve ter um endereço exclusivo. O endereço do EndpointAddress ponto de extremidade é representado pela classe, que contém um URI (Uniform Resource Identifier) que representa o endereço do serviço, um Identity, que representa a identidade de segurança do serviço e uma coleção de opcionais Headers. Os cabeçalhos opcionais fornecem informações de endereçamento mais detalhadas para identificar ou interagir com o ponto de extremidade. Por exemplo, os cabeçalhos podem indicar como processar uma mensagem de entrada, onde o ponto de extremidade deve enviar uma mensagem de resposta ou qual instância de um serviço usar para processar uma mensagem de entrada de um usuário específico quando várias instâncias estiverem disponíveis.

Definição de um endereço de ponto final

No WCF, um EndpointAddress modela uma referência de ponto de extremidade (EPR) conforme definido no padrão WS-Addressing.

O endereço URI para a maioria dos transportes tem quatro partes. Por exemplo, este URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint tem as seguintes quatro partes:

  • Esquema: http:

  • Máquina: www.fabrikam.com

  • (Opcional) Porta: 322

  • Caminho: /mathservice.svc/secureEndpoint

Parte do modelo EPR é que cada referência de ponto final pode conter alguns parâmetros de referência que adicionam informações de identificação extras. No WCF, esses parâmetros de referência são modelados como instâncias da AddressHeader classe.

O endereço do ponto de extremidade de um serviço pode ser especificado imperativamente usando código ou declarativamente por meio da configuração. Definir pontos de extremidade no código geralmente não é prático porque as ligações e endereços para um serviço implantado geralmente são diferentes daqueles usados enquanto o serviço está sendo desenvolvido. Geralmente, é mais prático definir pontos de extremidade de serviço usando configuração em vez de código. Manter as informações de vinculação e endereçamento fora do código permite que eles sejam alterados sem ter que recompilar e reimplantar o aplicativo. Se nenhum ponto de extremidade for especificado no código ou na configuração, o tempo de execução adicionará um ponto de extremidade padrão em cada endereço base para cada contrato implementado pelo serviço.

Há duas maneiras de especificar endereços de ponto de extremidade para um serviço no WCF. Você pode especificar um endereço absoluto para cada ponto de extremidade associado ao serviço ou pode fornecer um endereço base para o ServiceHost de um serviço e, em seguida, especificar um endereço para cada ponto de extremidade associado a esse serviço que é definido em relação a esse endereço base. Você pode usar cada um desses procedimentos para especificar os endereços de ponto de extremidade para um serviço em configuração ou código. Se você não especificar um endereço relativo, o serviço usará o endereço base. Você também pode ter vários endereços base para um serviço, mas cada serviço é permitido apenas um endereço base para cada transporte. Se você tiver vários pontos de extremidade, cada um dos quais é configurado com uma associação diferente, seus endereços devem ser exclusivos. Os pontos de extremidade que usam a mesma vinculação, mas contratos diferentes, podem usar o mesmo endereço.

Ao hospedar com o IIS, você não gerencia a ServiceHost instância sozinho. O endereço base é sempre o endereço especificado no arquivo .svc para o serviço ao hospedar no IIS. Portanto, você deve usar endereços de ponto de extremidade relativos para pontos de extremidade de serviço hospedados no IIS. Fornecer um endereço de ponto de extremidade totalmente qualificado pode levar a erros na implantação do serviço. Para obter mais informações, consulte Implantando um serviço WCF hospedado pelos Serviços de Informações da Internet.

Definindo endereços de ponto de extremidade na configuração

Para definir um ponto de extremidade em um arquivo de configuração, use o <elemento endpoint> .

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello"/>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Quando o Open método é chamado (ou seja, quando o aplicativo de hospedagem tenta iniciar o serviço), o sistema procura um <elemento de serviço com um atributo name> que especifica "UE. Samples.HelloService". Se o <elemento de serviço for encontrado, o sistema carregará a classe especificada e criará pontos de extremidade usando as definições de ponto de> extremidade fornecidas no arquivo de configuração. Esse mecanismo permite que você carregue e inicie um serviço com duas linhas de código, mantendo a vinculação e endereçamento de informações fora do seu código. A vantagem dessa abordagem é que essas alterações podem ser feitas sem a necessidade de recompilar ou reimplantar o aplicativo.

Os cabeçalhos opcionais são declarados em cabeçalhos><. A seguir está um exemplo dos elementos usados para especificar pontos de extremidade para um serviço em um arquivo de configuração que distingue entre dois cabeçalhos: clientes "Gold" de http://tempuri1.org/ e clientes "Standard" de http://tempuri2.org/. O cliente que chama esse serviço deve ter os cabeçalhos apropriados <em seu arquivo de> configuração.

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri1.org/">Gold</Member>
          </headers>
        </endpoint>
        <endpoint address="/Address2"
          binding="basicHttpBinding" 
          contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri2.org/">Silver</Member>
          </headers>
        </endpoint>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Os cabeçalhos também podem ser definidos em mensagens individuais em vez de todas as mensagens em um ponto de extremidade (como mostrado anteriormente). Isso é feito usando OperationContextScope para criar um novo contexto em um aplicativo cliente para adicionar um cabeçalho personalizado à mensagem de saída, conforme mostrado no exemplo a seguir.

SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
  using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
  {
    MessageHeader header
      = MessageHeader.CreateHeader(
      "Service-Bound-CustomHeader",
      "http://Microsoft.WCF.Documentation",
      "Custom Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // Making calls.
    Console.WriteLine("Enter the greeting to send: ");
    string greeting = Console.ReadLine();

    //Console.ReadLine();
    header = MessageHeader.CreateHeader(
        "Service-Bound-OneWayHeader",
        "http://Microsoft.WCF.Documentation",
        "Different Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // One-way
    wcfClient.Push(greeting);
    this.wait.WaitOne();

    // Done with service.
    wcfClient.Close();
    Console.WriteLine("Done!");
    Console.ReadLine();
  }
}
catch (TimeoutException timeProblem)
{
  Console.WriteLine("The service operation timed out. " + timeProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
  Console.WriteLine("There was a communication problem. " + commProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
    Using scope As New OperationContextScope(wcfClient.InnerChannel)
        Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
                            "http://Microsoft.WCF.Documentation", "Custom Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' Making calls.
        Console.WriteLine("Enter the greeting to send: ")
        Dim greeting As String = Console.ReadLine()

        'Console.ReadLine();
        header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
                                            "http://Microsoft.WCF.Documentation", "Different Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' One-way
        wcfClient.Push(greeting)
        Me.wait.WaitOne()

        ' Done with service. 
        wcfClient.Close()
        Console.WriteLine("Done!")
        Console.ReadLine()
    End Using
Catch timeProblem As TimeoutException
    Console.WriteLine("The service operation timed out. " & timeProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
Catch commProblem As CommunicationException
    Console.WriteLine("There was a communication problem. " & commProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
End Try

Endereço do ponto de extremidade nos metadados

Um endereço de ponto de extremidade é representado no WSDL (Web Services Description Language) como um elemento WS-Addressing EndpointReference (EPR) dentro do elemento do ponto de wsdl:port extremidade correspondente. O EPR contém o endereço do ponto de extremidade, bem como quaisquer propriedades de endereço. Observe que o EPR dentro wsdl:port substitui soap:Address como visto no exemplo a seguir.

Definindo endereços de ponto de extremidade no código

Um endereço de ponto de extremidade pode ser criado em código com a EndpointAddress classe. O URI especificado para o endereço do ponto de extremidade pode ser um caminho totalmente qualificado ou um caminho relativo ao endereço base do serviço. O código a seguir ilustra como criar uma instância da EndpointAddress classe e adicioná-la à ServiceHost instância que está hospedando o serviço.

O exemplo a seguir demonstra como especificar o endereço completo do ponto de extremidade no código.

Uri baseAddress = new Uri("http://localhost:8000/HelloService");
string address = "http://localhost:8000/HelloService/MyService";

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

O exemplo a seguir demonstra como adicionar um endereço relativo ("MyService") ao endereço base do host de serviço.

Uri baseAddress = new Uri("http://localhost:8000/HelloService");

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

Nota

As propriedades do no aplicativo de ServiceDescription serviço não devem ser modificadas posteriormente ao OnOpening método em ServiceHostBase. Alguns membros, como a Credentials propriedade e os AddServiceEndpoint métodos on ServiceHostBase e ServiceHost, lançam uma exceção se modificados após esse ponto. Outros permitem modificá-los, mas o resultado é indefinido.

Da mesma forma, no cliente os ServiceEndpoint valores não devem ser modificados após a chamada para OnOpening no ChannelFactory. A Credentials propriedade lança uma exceção se modificada após esse ponto. Os outros valores de descrição do cliente podem ser modificados sem erro, mas o resultado é indefinido.

Seja para o serviço ou cliente, é recomendável que você modifique a descrição antes de chamar Open.

Usando pontos de extremidade padrão

Se nenhum ponto de extremidade for especificado no código ou na configuração, o tempo de execução fornecerá pontos de extremidade padrão adicionando um ponto de extremidade padrão em cada endereço base para cada contrato de serviço implementado pelo serviço. O endereço base pode ser especificado no código ou na configuração, e os pontos de extremidade padrão são adicionados quando Open é chamado no ServiceHost.

Se os pontos de extremidade forem fornecidos explicitamente, os pontos de extremidade padrão ainda poderão ser adicionados chamando AddDefaultEndpoints o botão antes de chamar Open.ServiceHost Para obter mais informações sobre pontos de extremidade padrão, associações e comportamentos, consulte Configuração simplificada e configuração simplificada para serviços WCF.

Consulte também