Udostępnij za pośrednictwem


Określanie adresu punktu końcowego

Cała komunikacja z usługą Windows Communication Foundation (WCF) odbywa się za pośrednictwem jego punktów końcowych. Każda z nich ServiceEndpoint zawiera Addresswartości , a Bindingi Contract. Kontrakt określa, które operacje są dostępne. Powiązanie określa, jak komunikować się z usługą, a adres określa, gdzie można znaleźć usługę. Każdy punkt końcowy musi mieć unikatowy adres. Adres punktu końcowego EndpointAddress jest reprezentowany przez klasę, która zawiera identyfikator URI (Uniform Resource Identifier), który reprezentuje adres usługi , Identityczyli , który reprezentuje tożsamość zabezpieczeń usługi i kolekcję opcjonalnych Headers. Opcjonalne nagłówki zawierają bardziej szczegółowe informacje dotyczące adresowania w celu zidentyfikowania punktu końcowego lub interakcji z nim. Na przykład nagłówki mogą wskazywać, jak przetworzyć komunikat przychodzący, gdzie punkt końcowy powinien wysłać wiadomość odpowiedzi lub które wystąpienie usługi do użycia w celu przetworzenia wiadomości przychodzącej od określonego użytkownika, gdy dostępnych jest wiele wystąpień.

Definicja adresu punktu końcowego

W programie WCF modeluje EndpointAddress odwołanie do punktu końcowego (EPR), zgodnie z definicją w standardzie WS-Addressing.

Identyfikator URI adresu dla większości transportów ma cztery części. Na przykład ten identyfikator URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint ma następujące cztery części:

  • Schemat: http:

  • Maszyny: www.fabrikam.com

  • (Opcjonalnie) Port: 322

  • Ścieżka: /mathservice.svc/secureEndpoint

Częścią modelu EPR jest to, że każde odwołanie do punktu końcowego może zawierać pewne parametry referencyjne, które dodają dodatkowe informacje identyfikujące. W programie WCF te parametry referencyjne są modelowane jako wystąpienia AddressHeader klasy.

Adres punktu końcowego dla usługi można określić w sposób imperatywne przy użyciu kodu lub deklaratywnego za pośrednictwem konfiguracji. Definiowanie punktów końcowych w kodzie zwykle nie jest praktyczne, ponieważ powiązania i adresy wdrożonej usługi zwykle różnią się od tych używanych podczas opracowywania usługi. Ogólnie rzecz biorąc, bardziej praktyczne jest definiowanie punktów końcowych usługi przy użyciu konfiguracji, a nie kodu. Utrzymywanie powiązania i adresowania informacji poza kodem umożliwia ich zmianę bez konieczności ponownego kompilowania i ponownego wdrażania aplikacji. Jeśli w kodzie lub w konfiguracji nie określono żadnych punktów końcowych, środowisko uruchomieniowe dodaje jeden domyślny punkt końcowy na każdym adresie podstawowym dla każdego kontraktu zaimplementowanego przez usługę.

Istnieją dwa sposoby określania adresów punktów końcowych dla usługi w programie WCF. Można określić adres bezwzględny dla każdego punktu końcowego skojarzonego z usługą lub podać adres ServiceHost podstawowy dla usługi, a następnie określić adres dla każdego punktu końcowego skojarzonego z tą usługą zdefiniowaną względem tego adresu podstawowego. Za pomocą każdej z tych procedur można określić adresy punktów końcowych dla usługi w konfiguracji lub kodzie. Jeśli nie określisz adresu względnego, usługa używa adresu podstawowego. Można również mieć wiele adresów bazowych dla usługi, ale każda usługa jest dozwolona tylko jeden adres podstawowy dla każdego transportu. Jeśli masz wiele punktów końcowych, z których każdy jest skonfigurowany przy użyciu innego powiązania, ich adresy muszą być unikatowe. Punkty końcowe używające tego samego powiązania, ale różne kontrakty mogą używać tego samego adresu.

Hostowanie za pomocą usług IIS nie ServiceHost jest zarządzane samodzielnie. Adres podstawowy jest zawsze adresem określonym w pliku svc dla usługi podczas hostowania w usługach IIS. Dlatego należy używać względnych adresów punktów końcowych dla punktów końcowych usługi hostowanej przez usługi IIS. Podanie w pełni kwalifikowanego adresu punktu końcowego może prowadzić do błędów we wdrożeniu usługi. Aby uzyskać więcej informacji, zobacz Wdrażanie internetowej usługi informacyjnej hostowanej w programie WCF.

Definiowanie adresów punktów końcowych w konfiguracji

Aby zdefiniować punkt końcowy w pliku konfiguracji, użyj elementu punktu końcowego><.

<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>

Open Gdy metoda jest wywoływana (czyli gdy aplikacja hostingowa próbuje uruchomić usługę), system szuka <elementu usługi> o atrybucie name, który określa "UE. Samples.HelloService". <Jeśli element usługi> zostanie znaleziony, system ładuje określoną klasę i tworzy punkty końcowe przy użyciu definicji punktów końcowych podanych w pliku konfiguracji. Ten mechanizm umożliwia ładowanie i uruchamianie usługi z dwoma wierszami kodu przy zachowaniu powiązania i adresowania informacji poza kodem. Zaletą tego podejścia jest możliwość wprowadzenia tych zmian bez konieczności ponownego kompilowania lub ponownego wdrażania aplikacji.

Opcjonalne nagłówki są deklarowane w nagłówkach>.< Poniżej przedstawiono przykład elementów używanych do określania punktów końcowych dla usługi w pliku konfiguracji, który rozróżnia dwa nagłówki: "Gold" klientów z http://tempuri1.org/ i "Standardowa" klientów z http://tempuri2.org/. Klient wywołujący tę usługę musi mieć odpowiednie <nagłówki> w pliku konfiguracji.

<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>

Nagłówki można również ustawić na poszczególnych komunikatach zamiast wszystkich komunikatów w punkcie końcowym (jak pokazano wcześniej). Odbywa się to przy użyciu polecenia OperationContextScope w celu utworzenia nowego kontekstu w aplikacji klienckiej w celu dodania niestandardowego nagłówka do komunikatu wychodzącego, jak pokazano w poniższym przykładzie.

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

Adres punktu końcowego w metadanych

Adres punktu końcowego jest reprezentowany w języku WSDL (Web Services Description Language) jako element EPR (WS-Address EndpointReference ) wewnątrz odpowiedniego elementu punktu końcowego wsdl:port . EPR zawiera adres punktu końcowego oraz wszelkie właściwości adresu. Należy pamiętać, że wewnętrzne resetowanie hasła wsdl:port jest zastępowane soap:Address , jak pokazano w poniższym przykładzie.

Definiowanie adresów punktów końcowych w kodzie

Adres punktu końcowego można utworzyć w kodzie z klasą EndpointAddress . Identyfikator URI określony dla adresu punktu końcowego może być w pełni kwalifikowaną ścieżką lub ścieżką względną względem adresu podstawowego usługi. Poniższy kod ilustruje sposób tworzenia wystąpienia EndpointAddress klasy i dodawania go do ServiceHost wystąpienia hostujące usługę.

W poniższym przykładzie pokazano, jak określić pełny adres punktu końcowego w kodzie.

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();
}

W poniższym przykładzie pokazano, jak dodać względny adres ("MyService") do podstawowego adresu hosta usługi.

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();
}

Uwaga

ServiceDescription Właściwości obiektu w aplikacji usługi nie mogą być modyfikowane po metodzie OnOpening w pliku ServiceHostBase. Niektóre elementy członkowskie, takie jak Credentials właściwość i AddServiceEndpoint metody w systemach ServiceHostBase i ServiceHost, zgłaszają wyjątek w przypadku modyfikacji po tym punkcie. Inni zezwalają na ich modyfikowanie, ale wynik jest niezdefiniowany.

Podobnie na kliencie ServiceEndpoint wartości nie mogą być modyfikowane po wywołaniu OnOpeningChannelFactorymetody na . Właściwość Credentials zgłasza wyjątek, jeśli został zmodyfikowany po tym punkcie. Inne wartości opisu klienta można modyfikować bez błędu, ale wynik jest niezdefiniowany.

Niezależnie od tego, czy jest to usługa, czy klient, zaleca się zmodyfikowanie opisu przed wywołaniem metody Open.

Używanie domyślnych punktów końcowych

Jeśli w kodzie lub w konfiguracji nie określono żadnych punktów końcowych, środowisko uruchomieniowe udostępnia domyślne punkty końcowe przez dodanie jednego domyślnego punktu końcowego na każdym adresie podstawowym dla każdego kontraktu usługi zaimplementowanego przez usługę. Adres podstawowy można określić w kodzie lub w konfiguracji, a domyślne punkty końcowe są dodawane, gdy Open jest wywoływany ServiceHostna .

Jeśli punkty końcowe są jawnie udostępniane, domyślne punkty końcowe mogą być nadal dodawane przez wywołanie metody przed ServiceHost wywołaniem AddDefaultEndpoints metody Open. Aby uzyskać więcej informacji na temat domyślnych punktów końcowych, powiązań i zachowań, zobacz Uproszczone konfigurowanie i uproszczona konfiguracja usług WCF.

Zobacz też