Bagikan melalui


Menentukan Alamat Titik Akhir

Semua komunikasi dengan layanan Windows Communication Foundation (WCF) terjadi melalui titik akhirnya. Masing-masing ServiceEndpoint berisi Address, Binding, dan Contract. Kontrak menentukan operasi mana yang tersedia. Pengikatan menentukan cara berkomunikasi dengan layanan, dan alamat menentukan tempat menemukan layanan. Setiap titik akhir harus memiliki alamat yang unik. Alamat titik akhir diwakili oleh kelas EndpointAddress, yang berisi Pengidentifikasi Sumber Daya Seragam (URI) yang mewakili alamat layanan, Identity, yang mewakili identitas keamanan layanan, dan kumpulan Headers opsional. Header opsional memberikan informasi pengalamatan yang lebih detail untuk mengidentifikasi atau berinteraksi dengan titik akhir. Misalnya, header dapat menunjukkan cara memproses pesan masuk, di mana titik akhir harus mengirim pesan balasan, atau instans layanan mana yang digunakan untuk memproses pesan masuk dari pengguna tertentu ketika beberapa instans tersedia.

Definisi Alamat Titik Akhir

Di WCF, EndpointAddress memodelkan referensi titik akhir (EPR) seperti yang ditentukan dalam standar WS-Addressing.

Alamat URI untuk sebagian besar transportasi memiliki empat bagian. Misalnya, URI ini, http://www.fabrikam.com:322/mathservice.svc/secureEndpoint memiliki empat bagian berikut:

  • Skema: http:

  • Mesin: www.fabrikam.com

  • (Opsional) Port: 322

  • Jalur: /mathservice.svc/secureEndpoint

Bagian dari model EPR adalah bahwa setiap referensi titik akhir dapat membawa beberapa parameter referensi yang menambahkan informasi identifikasi tambahan. Dalam WCF, parameter referensi ini dimodelkan sebagai instans kelas AddressHeader.

Alamat titik akhir untuk suatu layanan dapat ditentukan baik secara imperatif dengan menggunakan kode atau secara deklaratif melalui konfigurasi. Menentukan titik akhir dalam kode biasanya tidak praktis karena pengikatan dan alamat untuk layanan yang disebarkan biasanya berbeda dari yang digunakan saat layanan sedang dikembangkan. Umumnya, lebih praktis menentukan titik akhir layanan menggunakan konfigurasi, bukan kode. Menjaga informasi pengikatan dan pengalamatan di luar kode memungkinkan informasi tersebut berubah tanpa harus mengompilasi ulang dan menyebarkan ulang aplikasi. Jika tidak ada titik akhir yang ditentukan dalam kode atau dalam konfigurasi, runtime menambahkan satu titik akhir default pada setiap alamat dasar untuk setiap kontrak yang diimplementasikan oleh layanan.

Ada dua cara untuk menentukan alamat titik akhir untuk layanan di WCF. Anda dapat menentukan alamat absolut untuk setiap titik akhir yang terkait dengan layanan atau Anda dapat memberikan alamat dasar untuk ServiceHost layanan dan kemudian menentukan alamat untuk setiap titik akhir yang terkait dengan layanan ini yang ditentukan relatif terhadap alamat dasar ini. Anda dapat menggunakan masing-masing prosedur ini untuk menentukan alamat titik akhir untuk layanan baik dalam konfigurasi atau kode. Jika Anda tidak menentukan alamat relatif, layanan menggunakan alamat dasar. Anda juga dapat memiliki beberapa alamat dasar untuk layanan, tetapi setiap layanan hanya diizinkan satu alamat dasar untuk setiap transportasi. Jika Anda memiliki beberapa titik akhir, yang masing-masing dikonfigurasi dengan pengikatan yang berbeda, alamatnya harus unik. Titik akhir yang menggunakan pengikatan yang sama tetapi kontrak yang berbeda dapat menggunakan alamat yang sama.

Saat menghosting dengan IIS, Anda tidak mengelola instans ServiceHost secara mandiri. Alamat dasar selalu berupa alamat yang ditentukan dalam file .svc untuk layanan saat menghosting di IIS. Jadi Anda harus menggunakan alamat titik akhir relatif untuk titik akhir layanan yang dihosting IIS. Menyediakan alamat titik akhir yang sepenuhnya memenuhi syarat dapat menyebabkan kesalahan dalam penyebaran layanan. Untuk informasi selengkapnya, lihat Menyebarkan Layanan WCF yang Dihost Layanan Informasi Internet.

Menentukan Alamat Titik Akhir dalam Konfigurasi

Untuk menentukan titik akhir dalam file konfigurasi, gunakan elemen <titik akhir>.

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

Ketika metode Open dipanggil (yaitu, ketika aplikasi hosting mencoba memulai layanan), sistem mencari elemen <layanan> dengan atribut nama yang menentukan "UE.Samples.HelloService". Jika elemen <layanan> ditemukan, sistem memuat kelas yang ditentukan dan membuat titik akhir menggunakan definisi titik akhir yang disediakan dalam file konfigurasi. Mekanisme ini memungkinkan Anda untuk memuat dan memulai layanan dengan dua baris kode sambil menjaga informasi pengikatan dan pengalamatan dari kode Anda. Keuntungan dari pendekatan ini adalah bahwa perubahan ini dapat dilakukan tanpa harus mengompilasi ulang atau menyebarkan ulang aplikasi.

Header opsional dinyatakan dalam <header>. Berikut ini adalah contoh elemen yang digunakan untuk menentukan titik akhir untuk layanan dalam file konfigurasi yang membedakan antara dua header: klien "Gold" dari http://tempuri1.org/ dan klien "Standar" dari http://tempuri2.org/. Klien yang memanggil layanan ini harus memiliki <header> yang sesuai dalam file konfigurasinya.

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

Header juga dapat diatur pada pesan individual, bukan semua pesan pada titik akhir (seperti yang ditunjukkan sebelumnya). Hal ini dilakukan dengan menggunakan OperationContextScope untuk membuat konteks baru dalam aplikasi klien untuk menambahkan header kustom ke pesan keluar, seperti yang ditunjukkan dalam contoh berikut.

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

Alamat Titik Akhir dalam Metadata

Alamat titik akhir diwakili dalam Bahasa Deskripsi Layanan Web (WSDL) sebagai elemen WS-Addressing EndpointReference (EPR) di dalam elemen wsdl:port titik akhir yang sesuai. EPR berisi alamat titik akhir serta properti alamat apa pun. Perhatikan bahwa EPR di dalam wsdl:port menggantikan soap:Address seperti yang terlihat dalam contoh berikut.

Menentukan Alamat Titik Akhir dalam Kode

Alamat titik akhir dapat dibuat dalam kode dengan kelas EndpointAddress. URI yang ditentukan untuk alamat titik akhir dapat menjadi jalur yang sepenuhnya memenuhi syarat atau jalur yang relatif terhadap alamat dasar layanan. Kode berikut mengilustrasikan cara membuat instans kelas EndpointAddress dan menambahkannya ke instans ServiceHost yang menghosting layanan.

Contoh berikut menunjukkan cara menentukan alamat titik akhir lengkap dalam kode.

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

Contoh berikut menunjukkan cara menambahkan alamat relatif ("MyService") ke alamat dasar host layanan.

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

Catatan

Properti dari ServiceDescription dalam aplikasi layanan tidak boleh dimodifikasi berikutnya ke metode OnOpening pada ServiceHostBase. Beberapa anggota, seperti properti Credentials dan metode AddServiceEndpoint pada ServiceHostBase dan ServiceHost, menampilkan pengecualian jika dimodifikasi setelah titik tersebut. Yang lain mengizinkan Anda untuk memodifikasinya, tetapi hasilnya tidak ditentukan.

Demikian pula, pada klien, nilai ServiceEndpoint tidak boleh dimodifikasi setelah panggilan ke OnOpening pada ChannelFactory. Properti Credentials menampilkan pengecualian jika dimodifikasi setelah titik tersebut. Nilai deskripsi klien lainnya dapat dimodifikasi tanpa kesalahan, tetapi hasilnya tidak ditentukan.

Baik untuk layanan atau klien, sebaiknya Anda mengubah deskripsi sebelum memanggil Open.

Menggunakan Titik Akhir Default

Jika tidak ada titik akhir yang ditentukan dalam kode atau dalam konfigurasi maka runtime menyediakan titik akhir default dengan menambahkan satu titik akhir default pada setiap alamat dasar untuk setiap kontrak layanan yang diimplementasikan oleh layanan. Alamat dasar dapat ditentukan dalam kode atau dalam konfigurasi, dan titik akhir default ditambahkan jika Open dipanggil pada ServiceHost.

Jika titik akhir disediakan secara eksplisit, titik akhir default masih dapat ditambahkan dengan memanggil AddDefaultEndpoints pada ServiceHost sebelum memanggil Open. Untuk informasi selengkapnya tentang titik akhir, pengikatan, dan perilaku default, lihat Konfigurasi Sederhana dan Konfigurasi Sederhana untuk Layanan WCF.

Lihat juga