Sdílet prostřednictvím


Zadání adresy koncového bodu

Veškerá komunikace se službou Windows Communication Foundation (WCF) probíhá prostřednictvím jejích koncových bodů. Každý ServiceEndpoint obsahuje Address, Binding a Contract. Kontrakt určuje, které operace jsou k dispozici. Vazba určuje způsob komunikace se službou a adresa určuje, kde se má služba najít. Každý koncový bod musí mít jedinečnou adresu. Adresa koncového bodu je reprezentována třídou EndpointAddress, která obsahuje identifikátor URI (Uniform Resource Identifier), jenž představuje adresu služby, atribut Identity, který reprezentuje bezpečnostní identitu služby, a kolekci volitelných Headers. Volitelné hlavičky poskytují podrobnější informace o adresování k identifikaci koncového bodu nebo interakci s ním. Hlavičky můžou například znamenat, jak zpracovat příchozí zprávu, kde má koncový bod odeslat zprávu odpovědi nebo jakou instanci služby použít ke zpracování příchozí zprávy od konkrétního uživatele, když je k dispozici více instancí.

Definice adresy koncového bodu

Ve WCF EndpointAddress modeluje odkaz na koncový bod (EPR) definovaný v WS-Addressing standardu.

Identifikátor URI adresy pro většinu přenosů má čtyři části. Tento identifikátor URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint má například následující čtyři části:

  • Schéma: http:

  • Stroj: www.fabrikam.com

  • (Volitelné) Port: 322

  • Cesta: /mathservice.svc/secureEndpoint

Součástí modelu EPR je, že každý odkaz na koncový bod může obsahovat některé referenční parametry, které přidávají další identifikační informace. Ve WCF jsou tyto referenční parametry modelovány jako instance AddressHeader třídy.

Adresu koncového bodu pro službu je možné zadat buď imperativním použitím kódu, nebo deklarativní prostřednictvím konfigurace. Definování koncových bodů v kódu obvykle není praktické, protože vazby a adresy nasazené služby se obvykle liší od těch, které se používají při vývoji služby. Obecně je vhodnější definovat koncové body služby pomocí konfigurace místo kódu. Udržování vazby a adresování informací mimo kód jim umožňuje změnit, aniž by bylo nutné aplikaci znovu zkompilovat a znovu nasadit. Pokud nejsou v kódu nebo v konfiguraci zadány žádné koncové body, modul runtime přidá jeden výchozí koncový bod na každou základní adresu pro každou smlouvu implementovanou službou.

Existují dva způsoby, jak zadat adresy koncových bodů pro službu ve WCF. Můžete zadat absolutní adresu pro každý koncový bod přidružený ke službě nebo můžete zadat základní adresu pro ServiceHost službu a pak zadat adresu pro každý koncový bod přidružený k této službě, který je definován vzhledem k této základní adrese. Každý z těchto postupů můžete použít k určení adres koncových bodů pro službu v konfiguraci nebo kódu. Pokud nezadáte relativní adresu, služba použije základní adresu. Pro službu můžete mít také více základních adres, ale každá služba má pro každý přenos povolenou jenom jednu základní adresu. Pokud máte více koncových bodů, z nichž každá je nakonfigurovaná s jinou vazbou, musí být jejich adresy jedinečné. Koncové body, které používají stejnou vazbu, ale různé kontrakty můžou používat stejnou adresu.

Při hostování se službou ServiceHost IIS nespravujete instanci sami. Základní adresa je vždy adresa zadaná v souboru .svc pro službu při hostování ve službě IIS. Proto je nutné použít relativní adresy koncových bodů pro koncové body služby hostované službou IIS. Poskytnutí plně kvalifikované adresy koncového bodu může vést k chybám při nasazování služby. Další informace naleznete v tématu Nasazení internetové informační Services-Hosted SLUŽBY WCF.

Definování adres koncových bodů v konfiguraci

K definování koncového bodu v konfiguračním souboru použijte prvek koncového< bodu>.

<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 Při volání metody (to znamená, když se hostitelská aplikace pokusí spustit službu), systém vyhledá <element služby> s atributem name, který je nastaven na "UE.Samples.HelloService". Pokud se najde prvek <služby>, systém načte zadanou třídu a vytvoří koncové body pomocí definic koncových bodů v zadaném konfiguračním souboru. Tento mechanismus umožňuje načíst a spustit službu pomocí dvou řádů kódu, aniž byste vkládali informace o vazbách a adresování do svého kódu. Výhodou tohoto přístupu je, že tyto změny je možné provést, aniž by bylo nutné aplikaci znovu zkompilovat nebo znovu nasadit.

Volitelná záhlaví jsou deklarována v <hlavičkách>. Následuje příklad prvků použitých k určení koncových bodů pro službu v konfiguračním souboru, který rozlišuje mezi dvěma typy klientů: "Gold" klienti z http://tempuri1.org/ a "Standard" klienti z http://tempuri2.org/. Klient, který tuto službu volá, musí mít v konfiguračním souboru odpovídající <hlavičky> .

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

Záhlaví je také možné nastavit pro jednotlivé zprávy místo všech zpráv v koncovém bodu (jak je znázorněno dříve). To se provádí pomocí OperationContextScope vytvoření nového kontextu v klientské aplikaci pro přidání vlastní hlavičky do odchozí zprávy, jak je znázorněno v následujícím příkladu.

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

Adresa koncového bodu v metadatech

Adresa koncového bodu je reprezentována v jazyce WSDL (Web Services Description Language) jako element WS-Addressing EndpointReference (EPR) uvnitř elementu odpovídajícího koncového wsdl:port bodu. EPR obsahuje adresu koncového bodu a také všechny vlastnosti adresy. Všimněte si, že EPR uvnitř wsdl:port nahrazuje soap:Address , jak je vidět v následujícím příkladu.

Definování adres koncových bodů v kódu

Adresu koncového bodu je možné vytvořit v kódu s EndpointAddress třídou. Identifikátor URI zadaný pro adresu koncového bodu může být plně kvalifikovaná cesta nebo cesta, která je relativní vzhledem k základní adrese služby. Následující kód ukazuje, jak vytvořit instanci EndpointAddress třídy a přidat ji do ServiceHost instance, která je hostitelem služby.

Následující příklad ukazuje, jak zadat úplnou adresu koncového bodu v kódu.

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

Následující příklad ukazuje, jak přidat relativní adresu ("MyService") na základní adresu hostitele služby.

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

Poznámka:

Vlastnosti ServiceDescription v aplikaci služby nesmí být změněny poté, co byla použita metoda OnOpening na ServiceHostBase. Někteří členové, například Credentials vlastnost a AddServiceEndpoint metody na ServiceHostBase a ServiceHost, vyvolají výjimku, pokud jsou po tomto bodu změněny. Ostatní vám umožňují je upravovat, ale výsledek je nedefinovaný.

Podobně na straně klienta nesmí být ServiceEndpoint hodnoty změněny po volání OnOpening na ChannelFactory straně. Vlastnost Credentials vyvolá výjimku, pokud je změněna po tomto bodu. Ostatní hodnoty popisu klienta je možné upravit bez chyby, ale výsledek není definován.

Bez ohledu na to, zda jde o službu či klienta, doporučujeme upravit popis před voláním Open.

Použití výchozích koncových bodů

Pokud nejsou zadány žádné koncové body v kódu nebo v konfiguraci, modul runtime poskytuje výchozí koncové body přidáním jednoho výchozího koncového bodu na každou základní adresu pro každý kontrakt služby implementovaný službou. Základní adresu lze zadat v kódu nebo v konfiguraci, a výchozí koncové body se přidají, když se Open zavolá na ServiceHost.

Pokud jsou koncové body explicitně zadané, je možné výchozí koncové body přidat voláním AddDefaultEndpointsServiceHost před voláním Open. Další informace o výchozích koncových bodech, vazbách a chování najdete v tématu Zjednodušená konfigurace a zjednodušená konfigurace pro služby WCF.

Viz také