Delen via


Een eindpuntadres opgeven

Alle communicatie met een WCF-service (Windows Communication Foundation) vindt plaats via de eindpunten. Elk ServiceEndpoint bevat een Address, een Bindingen een Contract. Het contract geeft aan welke bewerkingen beschikbaar zijn. De binding geeft aan hoe moet worden gecommuniceerd met de service en het adres geeft aan waar de service moet worden gevonden. Elk eindpunt moet een uniek adres hebben. Het eindpuntadres wordt vertegenwoordigd door de EndpointAddress klasse, die een URI (Uniform Resource Identifier) bevat die het adres van de service vertegenwoordigt, een Identity, die de beveiligingsidentiteit van de service vertegenwoordigt en een verzameling optioneel Headers. De optionele headers bieden gedetailleerdere adresseringsinformatie om het eindpunt te identificeren of ermee te communiceren. Kopteksten kunnen bijvoorbeeld aangeven hoe een binnenkomend bericht moet worden verwerkt, waarbij het eindpunt een antwoordbericht moet verzenden of welk exemplaar van een service moet worden gebruikt om een binnenkomend bericht van een bepaalde gebruiker te verwerken wanneer er meerdere exemplaren beschikbaar zijn.

Definitie van een eindpuntadres

In WCF modelleert een EndpointAddress eindpuntverwijzing (EPR) zoals gedefinieerd in de WS-Addressing-standaard.

De adres-URI voor de meeste transporten heeft vier delen. Deze URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint heeft bijvoorbeeld de volgende vier onderdelen:

  • Schema: http:

  • Machine: www.fabrikam.com

  • (Optioneel) Poort: 322

  • Pad: /mathservice.svc/secureEndpoint

Onderdeel van het EPR-model is dat elke eindpuntreferentie een aantal referentieparameters kan bevatten die extra identificatiegegevens toevoegen. In WCF worden deze referentieparameters gemodelleerd als exemplaren van de AddressHeader klasse.

Het eindpuntadres voor een service kan imperatief worden opgegeven met behulp van code of declaratief via configuratie. Het definiëren van eindpunten in code is meestal niet praktisch omdat de bindingen en adressen voor een geïmplementeerde service doorgaans afwijken van de bindingen en adressen die worden gebruikt terwijl de service wordt ontwikkeld. Over het algemeen is het praktischer om service-eindpunten te definiëren met behulp van configuratie in plaats van code. Door de bindings- en adresseringsgegevens buiten de code te houden, kunnen ze worden gewijzigd zonder de toepassing opnieuw te hoeven compileren en opnieuw te implementeren. Als er geen eindpunten zijn opgegeven in code of in de configuratie, voegt de runtime één standaardeindpunt toe op elk basisadres voor elk contract dat door de service wordt geïmplementeerd.

Er zijn twee manieren om eindpuntadressen op te geven voor een service in WCF. U kunt een absoluut adres opgeven voor elk eindpunt dat is gekoppeld aan de service of u kunt een basisadres opgeven voor de ServiceHost service en vervolgens een adres opgeven voor elk eindpunt dat is gekoppeld aan deze service die is gedefinieerd ten opzichte van dit basisadres. U kunt elk van deze procedures gebruiken om de eindpuntadressen voor een service op te geven in configuratie of code. Als u geen relatief adres opgeeft, gebruikt de service het basisadres. U kunt ook meerdere basisadressen voor een service hebben, maar elke service is slechts één basisadres toegestaan voor elk transport. Als u meerdere eindpunten hebt, die elk zijn geconfigureerd met een andere binding, moeten hun adressen uniek zijn. Eindpunten die dezelfde binding gebruiken, maar verschillende contracten kunnen hetzelfde adres gebruiken.

Wanneer u host met IIS, beheert u het ServiceHost exemplaar niet zelf. Het basisadres is altijd het adres dat is opgegeven in het .svc-bestand voor de service bij het hosten in IIS. U moet dus relatieve eindpuntadressen gebruiken voor service-eindpunten die worden gehost door IIS. Het leveren van een volledig gekwalificeerde eindpuntadres kan leiden tot fouten in de implementatie van de service. Zie Een door Internet Information Services gehoste WCF-service implementeren voor meer informatie.

Eindpuntadressen definiëren in configuratie

Als u een eindpunt in een configuratiebestand wilt definiëren, gebruikt u het eindpuntelement>.<

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

Wanneer de Open methode wordt aangeroepen (dat wil gezegd, wanneer de hostingtoepassing de service probeert te starten), zoekt het systeem naar een <service-element> met een naamkenmerk dat 'UE' aangeeft. Samples.HelloService". Als het <service-element> wordt gevonden, laadt het systeem de opgegeven klasse en maakt het eindpunten met behulp van de eindpuntdefinities die zijn opgegeven in het configuratiebestand. Met dit mechanisme kunt u een service laden en starten met twee regels code, terwijl u bindings- en adresseringsgegevens buiten uw code houdt. Het voordeel van deze aanpak is dat deze wijzigingen kunnen worden aangebracht zonder de toepassing opnieuw te hoeven compileren of opnieuw te implementeren.

De optionele headers worden gedeclareerd in een koptekst>.< Hier volgt een voorbeeld van de elementen die worden gebruikt voor het opgeven van eindpunten voor een service in een configuratiebestand dat onderscheid maakt tussen twee headers: "Gold"-clients van http://tempuri1.org/ en "Standard"-clients van http://tempuri2.org/. De client die deze service aanroept, moet de juiste <headers> in het configuratiebestand hebben.

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

Kopteksten kunnen ook worden ingesteld voor afzonderlijke berichten in plaats van alle berichten op een eindpunt (zoals eerder weergegeven). Dit wordt gedaan door OperationContextScope een nieuwe context te maken in een clienttoepassing om een aangepaste koptekst toe te voegen aan het uitgaande bericht, zoals wordt weergegeven in het volgende voorbeeld.

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

Eindpuntadres in metagegevens

Een eindpuntadres wordt weergegeven in WSDL (Web Services Description Language) als een EPR-element (WS-Addressing EndpointReference ) in het bijbehorende eindpuntelement wsdl:port . Het EPR bevat het adres van het eindpunt en alle adreseigenschappen. Houd er rekening mee dat het EPR in wsdl:port het volgende voorbeeld wordt vervangen soap:Address .

Eindpuntadressen definiëren in code

Er kan een eindpuntadres worden gemaakt in code met de EndpointAddress klasse. De URI die is opgegeven voor het eindpuntadres kan een volledig gekwalificeerd pad of een pad zijn dat relatief is ten opzichte van het basisadres van de service. De volgende code illustreert hoe u een exemplaar van de EndpointAddress klasse maakt en deze toevoegt aan het ServiceHost exemplaar dat als host fungeert voor de service.

In het volgende voorbeeld ziet u hoe u het volledige eindpuntadres in code opgeeft.

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

In het volgende voorbeeld ziet u hoe u een relatief adres ('MyService') toevoegt aan het basisadres van de servicehost.

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

Notitie

Eigenschappen van de ServiceDescription in de servicetoepassing mogen niet worden gewijzigd na de OnOpening methode op ServiceHostBase. Sommige leden, zoals de Credentials eigenschap en de AddServiceEndpoint methoden op ServiceHostBase en ServiceHost, genereren een uitzondering als deze na dat punt is gewijzigd. Anderen kunnen ze wijzigen, maar het resultaat is niet gedefinieerd.

Op dezelfde manier mogen de ServiceEndpoint waarden op de client niet worden gewijzigd na de aanroep naar OnOpening de ChannelFactory. De Credentials eigenschap genereert een uitzondering als deze na dat punt is gewijzigd. De andere clientbeschrijvingswaarden kunnen zonder fouten worden gewijzigd, maar het resultaat is niet gedefinieerd.

Of het nu gaat om de service of client, het wordt aanbevolen om de beschrijving te wijzigen voordat u aanroept Open.

Standaardeindpunten gebruiken

Als er geen eindpunten zijn opgegeven in code of in de configuratie, biedt de runtime standaardeindpunten door één standaardeindpunt toe te voegen op elk basisadres voor elk servicecontract dat door de service wordt geïmplementeerd. Het basisadres kan worden opgegeven in code of in de configuratie en de standaardeindpunten worden toegevoegd wanneer Open ze worden aangeroepen op de ServiceHost.

Als er expliciet eindpunten worden opgegeven, kunnen de standaardeindpunten nog steeds worden toegevoegd door het ServiceHost aanroepen aan te roepen voordat u aanroept.AddDefaultEndpointsOpen Zie Vereenvoudigde configuratie en vereenvoudigde configuratie voor WCF-services voor meer informatie over standaardeindpunten, bindingen en gedrag.

Zie ook