Bagikan melalui


Merancang Kontrak Layanan

Topik ini menjelaskan apa itu kontrak layanan, bagaimana kontrak tersebut ditentukan, operasi apa yang tersedia (dan implikasi untuk pertukaran pesan yang mendasarinya), jenis data apa yang digunakan, dan masalah lain yang membantu Anda merancang operasi yang memenuhi persyaratan skenario Anda.

Membuat Kontrak Layanan

Layanan mengekspos sejumlah operasi. Dalam aplikasi Windows Communication Foundation (WCF), tentukan operasi dengan membuat metode dan menandainya dengan atribut OperationContractAttribute. Kemudian, untuk membuat kontrak layanan, kelompokkan operasi Anda, baik dengan mendeklarasikannya dalam antarmuka yang ditandai dengan atribut ServiceContractAttribute, atau dengan mendefinisikannya dalam kelas yang ditandai dengan atribut yang sama. (Untuk contoh dasar, lihat Cara: Menentukan Kontrak Layanan.)

Metode apa pun yang tidak memiliki atribut OperationContractAttribute bukanlah operasi layanan dan tidak diekspos oleh layanan WCF.

Topik ini menjelaskan poin keputusan berikut saat merancang kontrak layanan:

  • Apakah akan menggunakan kelas atau antarmuka.

  • Cara menentukan jenis data yang ingin Anda tukarkan.

  • Jenis pola pertukaran yang dapat Anda gunakan.

  • Apakah Anda dapat menjadikan persyaratan keamanan eksplisit sebagai bagian dari kontrak.

  • Pembatasan untuk input dan output operasi.

Kelas atau Antarmuka

Kedua kelas dan antarmuka mewakili pengelompokan fungsionalitas dan, oleh karena itu, keduanya dapat digunakan untuk mendefinisikan kontrak layanan WCF. Namun, Anda disarankan untuk menggunakan antarmuka karena antarmuka tersebut secara langsung membuat model kontrak layanan. Tanpa implementasi, antarmuka tidak lebih dari mendefinisikan pengelompokan metode dengan tanda tangan tertentu. Mengimplementasikan antarmuka kontrak layanan dan Anda telah mengimplementasikan layanan WCF.

Semua manfaat antarmuka terkelola berlaku untuk antarmuka kontrak layanan:

  • Antarmuka kontrak layanan dapat memperluas sejumlah antarmuka kontrak layanan lainnya.

  • Kelas tunggal dapat mengimplementasikan sejumlah kontrak layanan dengan mengimplementasikan antarmuka kontrak layanan tersebut.

  • Anda dapat mengubah implementasi kontrak layanan dengan mengubah implementasi antarmuka, sementara kontrak layanan tetap sama.

  • Anda dapat membuat versi layanan Anda dengan mengimplementasikan antarmuka lama dan yang baru. Klien lama terhubung ke versi asli, sementara klien yang lebih baru dapat terhubung ke versi yang lebih baru.

Catatan

Saat mewarisi dari antarmuka kontrak layanan lain, Anda tidak dapat mengganti properti operasi, seperti nama atau namespace. Jika Anda mencoba melakukannya, Anda membuat operasi baru dalam kontrak layanan saat ini.

Untuk contoh penggunaan antarmuka guna membuat kontrak layanan, lihat Cara: Membuat Layanan dengan Antarmuka Kontrak.

Namun, Anda dapat menggunakan kelas untuk mendefinisikan kontrak layanan dan mengimplementasikan kontrak tersebut pada saat yang sama. Keuntungan membuat layanan Anda dengan menerapkan ServiceContractAttribute dan OperationContractAttribute langsung ke kelas dan metode di kelas, masing-masing, adalah kecepatan dan kesederhanaan. Kekurangannya adalah kelas terkelola tidak mendukung pewarisan berganda, dan akibatnya kelas terkelola hanya dapat mengimplementasikan satu kontrak layanan pada satu waktu. Selain itu, setiap modifikasi pada kelas atau tanda tangan metode memodifikasi kontrak publik untuk layanan tersebut, yang dapat mencegah klien yang tidak dimodifikasi menggunakan layanan Anda. Untuk informasi selengkapnya, lihat Mengimplementasikan Kontrak Layanan.

Untuk contoh yang menggunakan kelas untuk membuat kontrak layanan dan mengimplementasikannya secara bersamaan, lihat Cara: Membuat Layanan dengan Kelas Kontrak.

Pada titik ini, Anda harus memahami perbedaan antara mendefinisikan kontrak layanan dengan menggunakan antarmuka dan dengan menggunakan kelas. Langkah selanjutnya adalah memutuskan data apa yang dapat diteruskan bolak-balik antara layanan dan kliennya.

Parameter dan Nilai Pengembalian

Setiap operasi memiliki nilai pengembalian dan parameter, meskipun ini adalah void. Namun, tidak seperti metode lokal, di mana Anda dapat meneruskan referensi ke objek dari satu objek ke objek lain, operasi layanan tidak meneruskan referensi ke objek. Sebaliknya, operasi layanan meneruskan salinan objek.

Ini penting karena setiap jenis yang digunakan dalam parameter atau nilai pengembalian harus serial; yaitu, harus memungkinkan mengubah objek jenis tersebut menjadi aliran byte dan dari aliran byte menjadi objek.

Jenis primitif dapat diserialisasi secara default, seperti banyak jenis di .NET Framework.

Catatan

Nilai nama parameter dalam tanda tangan operasi adalah bagian dari kontrak dan peka huruf besar/kecil. Jika Anda ingin menggunakan nama parameter yang sama secara lokal tetapi mengubah nama dalam metadata yang diterbitkan, lihat System.ServiceModel.MessageParameterAttribute.

Kontrak Data

Aplikasi berorientasi layanan seperti aplikasi Windows Communication Foundation (WCF) dirancang untuk beroperasi dengan aplikasi klien sebanyak mungkin di platform Microsoft dan non-Microsoft. Untuk interoperabilitas seluas mungkin, sebaiknya Anda menandai jenis Anda dengan atribut DataContractAttribute dan DataMemberAttribute untuk membuat kontrak data, yang merupakan bagian dari kontrak layanan yang menjelaskan data yang dipertukarkan oleh operasi layanan Anda.

Kontrak data adalah kontrak gaya keikutsertaan: Tidak ada jenis atau anggota data yang diserialkan kecuali Anda secara eksplisit menerapkan atribut kontrak data. Kontrak data tidak terkait dengan cakupan akses kode yang dikelola: Anggota data pribadi dapat diserialisasikan dan dikirim ke tempat lain untuk diakses secara publik. (Untuk contoh dasar kontrak data, lihat Cara: Membuat Kontrak Data Dasar untuk Kelas atau Struktur.) WCF menangani definisi pesan SOAP yang mendasari yang mengaktifkan fungsionalitas operasi serta serialisasi jenis data Anda ke masuk dan keluar dari badan pesan. Selama jenis data Anda dapat diserialisasi, Anda tidak perlu memikirkan infrastruktur pertukaran pesan yang mendasarinya saat merancang operasi Anda.

Meskipun aplikasi WCF biasa menggunakan atribut DataContractAttribute dan DataMemberAttribute untuk membuat kontrak data operasi, Anda dapat menggunakan mekanisme serialisasi lainnya. Mekanisme standar ISerializable, SerializableAttribute, dan IXmlSerializable semuanya bekerja untuk menangani serialisasi jenis data Anda ke dalam pesan SOAP yang mendasar yang membawanya dari satu aplikasi ke aplikasi lain. Anda dapat menggunakan lebih banyak strategi serialisasi jika jenis data Anda memerlukan dukungan khusus. Untuk informasi selengkapnya tentang pilihan serialisasi jenis data dalam aplikasi WCF, lihat Menentukan Transfer Data dalam Kontrak Layanan.

Memetakan Parameter dan Mengembalikan Nilai ke Pertukaran Pesan

Operasi layanan didukung oleh pertukaran pesan SOAP yang mendasari yang mentransfer data aplikasi bolak-balik, selain data yang diperlukan oleh aplikasi untuk mendukung keamanan standar tertentu, transaksi, dan fitur terkait sesi. Karena ini masalahnya, tanda tangan operasi layanan menentukan pola pertukaran pesan (MEP) dasar tertentu yang dapat mendukung transfer data dan fitur yang diperlukan operasi. Anda dapat menentukan tiga pola dalam model pemrograman WCF: pola pesan permintaan/balasan, satu arah, dan dupleks.

Permintaan/Balas

Pola permintaan/balasan adalah pola di mana pengirim permintaan (aplikasi klien) menerima balasan yang dengannya permintaan tersebut berkorelasi. Ini adalah MEP default karena mendukung operasi di mana satu atau beberapa parameter diteruskan ke operasi dan nilai pengembalian diteruskan kembali ke pemanggil. Misalnya, contoh kode C# berikut menunjukkan operasi layanan dasar yang mengambil satu string dan mengembalikan string.

[OperationContractAttribute]  
string Hello(string greeting);  

Berikut ini adalah kode Visual Basic yang setara.

<OperationContractAttribute()>  
Function Hello (ByVal greeting As String) As String  

Tanda tangan operasi ini menentukan bentuk pertukaran pesan yang mendasarinya. Jika tidak ada korelasi, WCF tidak dapat menentukan untuk operasi mana nilai pengembalian dimaksudkan.

Perhatikan bahwa kecuali Anda menentukan pola pesan dasar yang berbeda, bahkan operasi layanan yang mengembalikan void (Nothing dalam Visual Basic) adalah pertukaran pesan permintaan/balasan. Hasil untuk operasi Anda adalah bahwa kecuali jika klien memanggil operasi secara asinkron, klien berhenti memproses hingga pesan balasan diterima, meskipun pesan tersebut kosong dalam kasus normal. Contoh kode C# berikut menunjukkan operasi yang tidak kembali hingga klien menerima pesan kosong sebagai respons.

[OperationContractAttribute]  
void Hello(string greeting);  

Berikut ini adalah kode Visual Basic yang setara.

<OperationContractAttribute()>  
Sub Hello (ByVal greeting As String)  

Contoh sebelumnya dapat memperlambat performa dan respons klien jika operasi membutuhkan waktu lama untuk dilakukan, tetapi ada keuntungan untuk meminta/membalas operasi bahkan ketika mereka mengembalikan void. Yang paling jelas adalah bahwa kesalahan SOAP dapat dikembalikan dalam pesan respons, yang menunjukkan bahwa beberapa kondisi kesalahan terkait layanan telah terjadi, baik dalam komunikasi atau pemrosesan. Kesalahan SOAP yang ditentukan dalam kontrak layanan diteruskan ke aplikasi klien sebagai objek FaultException<TDetail>, di mana parameter jenis adalah jenis yang ditentukan dalam kontrak layanan. Kesalahan ini membuat pemberitahuan kepada klien tentang kondisi kesalahan dalam layanan WCF menjadi mudah. Untuk informasi selengkapnya tentang pengecualian, kesalahan SOAP, dan penanganan kesalahan, lihat Menentukan dan Menangani Kesalahan dalam Kontrak dan Layanan. Untuk melihat contoh layanan dan klien permintaan/balasan, lihat Cara: Membuat Kontrak Permintaan-Balasan. Untuk informasi selengkapnya tentang masalah pola permintaan-balasan, lihat Layanan Permintaan-Balasan.

Satu-arah

Jika klien aplikasi layanan WCF tidak harus menunggu operasi selesai dan tidak memproses kesalahan SOAP, operasi dapat menentukan pola pesan satu arah. Operasi satu arah adalah operasi di mana klien memanggil operasi dan melanjutkan pemrosesan setelah WCF menulis pesan ke jaringan. Biasanya ini berarti bahwa kecuali jika data yang dikirim dalam pesan keluar sangat besar, klien terus berjalan segera (kecuali ada kesalahan pengiriman data). Jenis pola pertukaran pesan ini mendukung perilaku seperti peristiwa dari klien ke aplikasi layanan.

Pertukaran pesan di mana satu pesan dikirim dan tidak ada yang diterima tidak dapat mendukung operasi layanan yang menentukan nilai pengembalian selain void; dalam hal ini pengecualian InvalidOperationException ditampilkan.

Tidak ada pesan kembali juga berarti bahwa tidak ada kesalahan SOAP yang dikembalikan untuk menunjukkan kesalahan apa pun dalam pemrosesan atau komunikasi. (Mengkomunikasikan informasi kesalahan saat operasi adalah operasi satu arah memerlukan pola pertukaran pesan dupleks.)

Untuk menentukan pertukaran pesan satu arah untuk operasi yang mengembalikan void, atur properti IsOneWay ke true, seperti dalam contoh kode C# berikut.

[OperationContractAttribute(IsOneWay=true)]  
void Hello(string greeting);  

Berikut ini adalah kode Visual Basic yang setara.

<OperationContractAttribute(IsOneWay := True)>  
Sub Hello (ByVal greeting As String)  

Metode ini identik dengan contoh permintaan/balasan sebelumnya, tetapi mengatur properti IsOneWay ke true berarti bahwa meskipun metodenya identik, operasi layanan tidak mengirim pesan balasan dan klien segera kembali setelah pesan keluar telah diserahkan ke lapisan saluran. Sebagai contoh, lihat Cara: Membuat Kontrak Satu Arah. Untuk informasi selengkapnya tentang pola satu arah, lihat Layanan Satu Arah.

Dupleks

Pola dupleks ditandai dengan kemampuan layanan dan klien untuk mengirim pesan satu sama lain secara independen baik menggunakan pesan satu arah atau permintaan/balasan. Bentuk komunikasi dua arah ini berguna untuk layanan yang harus berkomunikasi langsung ke klien atau untuk memberikan pengalaman asinkron ke kedua sisi pertukaran pesan, termasuk perilaku seperti peristiwa.

Pola dupleks sedikit lebih kompleks daripada pola permintaan/balasan atau satu arah karena mekanisme tambahan untuk berkomunikasi dengan klien.

Untuk merancang kontrak dupleks, Anda juga harus merancang kontrak panggilan balik dan menetapkan jenis kontrak panggilan balik tersebut ke properti CallbackContract dari atribut ServiceContractAttribute yang menandai kontrak layanan Anda.

Untuk menerapkan pola dupleks, Anda harus membuat antarmuka kedua yang berisi deklarasi metode yang dipanggil pada klien.

Untuk contoh pembuatan layanan, dan klien yang mengakses layanan tersebut, lihat Cara: Membuat Kontrak Dupleks dan Cara: Mengakses Layanan dengan Kontrak Dupleks. Untuk contoh kerja, lihat Dupleks. Untuk informasi selengkapnya tentang masalah penggunaan kontrak dupleks, lihat Layanan Dupleks.

Perhatian

Saat layanan menerima pesan dupleks, layanan melihat elemen ReplyTo dalam pesan masuk tersebut untuk menentukan ke mana harus mengirim balasan. Jika saluran yang digunakan untuk menerima pesan tidak diamankan, maka klien yang tidak dipercaya dapat mengirim pesan berbahaya dengan ReplyTo mesin target, yang mengarah ke penolakan layanan (DOS) dari mesin target tersebut.

Parameter Keluar dan Ref

Dalam kebanyakan kasus, Anda dapat menggunakan parameter in (ByVal dalam Visual Basic) dan parameter out dan ref (ByRef dalam Visual Basic). Karena parameter out dan ref menunjukkan bahwa data dikembalikan dari operasi, tanda tangan operasi seperti berikut ini menetapkan bahwa operasi permintaan/balasan diperlukan meskipun tanda tangan operasi mengembalikan void.

[ServiceContractAttribute]  
public interface IMyContract  
{  
  [OperationContractAttribute]  
  public void PopulateData(ref CustomDataType data);  
}  

Berikut ini adalah kode Visual Basic yang setara.

<ServiceContractAttribute()> _  
Public Interface IMyContract  
  <OperationContractAttribute()> _  
  Public Sub PopulateData(ByRef data As CustomDataType)  
End Interface  

Satu-satunya pengecualian adalah kasus di mana tanda tangan Anda memiliki struktur tertentu. Misalnya, Anda dapat menggunakan pengikatan NetMsmqBinding untuk berkomunikasi dengan klien hanya jika metode yang digunakan untuk mendeklarasikan operasi mengembalikan void; tidak boleh ada nilai output, baik itu nilai pengembalian, parameter ref, atau out.

Selain itu, menggunakan parameter out atau ref mengharuskan operasi memiliki pesan respons yang mendasari untuk membawa kembali objek yang dimodifikasi. Jika operasi Anda adalah operasi satu arah, pengecualian InvalidOperationException ditampilkan pada runtime.

Tentukan Tingkat Perlindungan Pesan pada Kontrak

Saat merancang kontrak, Anda juga harus memutuskan tingkat perlindungan pesan dari layanan yang menerapkan kontrak Anda. Ini diperlukan hanya jika keamanan pesan diterapkan pada pengikatan di titik akhir kontrak. Jika pengikatan memiliki keamanan yang dimatikan (yaitu, jika pengikatan yang disediakan sistem mengatur System.ServiceModel.SecurityMode ke nilai SecurityMode.None), maka Anda tidak perlu memutuskan tingkat perlindungan pesan untuk kontrak tersebut. Dalam kebanyakan kasus, pengikatan yang disediakan sistem dengan keamanan tingkat pesan yang diterapkan memberikan tingkat perlindungan yang memadai dan Anda tidak perlu mempertimbangkan tingkat perlindungan untuk setiap operasi atau untuk setiap pesan.

Tingkat perlindungan adalah nilai yang menentukan apakah pesan (atau bagian pesan) yang mendukung layanan ditandatangani, ditandatangani dan dienkripsi, atau dikirim tanpa tanda tangan atau enkripsi. Tingkat perlindungan dapat diatur pada berbagai cakupan: Pada tingkat layanan, untuk operasi tertentu, untuk pesan dalam operasi tersebut, atau bagian pesan. Nilai yang ditetapkan pada satu cakupan menjadi nilai default untuk cakupan yang lebih kecil kecuali jika diganti secara eksplisit. Jika konfigurasi yang mengikat tidak dapat memberikan tingkat perlindungan minimum yang diperlukan untuk kontrak, pengecualian ditampilkan. Dan ketika tidak ada nilai tingkat perlindungan yang ditetapkan secara eksplisit pada kontrak, konfigurasi pengikatan mengontrol tingkat perlindungan untuk semua pesan jika pengikatan memiliki keamanan pesan. Ini adalah perilaku default.

Penting

Memutuskan apakah akan secara eksplisit menetapkan berbagai cakupan kontrak ke kurang dari tingkat perlindungan penuh ProtectionLevel.EncryptAndSign umumnya merupakan keputusan yang memperdagangkan beberapa tingkat keamanan untuk peningkatan performa. Dalam kasus ini, keputusan Anda harus berkisar pada operasi Anda dan nilai data yang mereka tukarkan. Untuk informasi selengkapnya, lihat Mengamankan Layanan.

Misalnya, contoh kode berikut tidak menetapkan properti ProtectionLevel atau ProtectionLevel pada kontrak.

[ServiceContract]  
public interface ISampleService  
{  
  [OperationContractAttribute]  
  public string GetString();  
  
  [OperationContractAttribute]  
  public int GetInt();
}  

Berikut ini adalah kode Visual Basic yang setara.

<ServiceContractAttribute()> _  
Public Interface ISampleService  
  
  <OperationContractAttribute()> _  
  Public Function GetString()As String  
  
  <OperationContractAttribute()> _  
  Public Function GetData() As Integer  
  
End Interface  

Saat berinteraksi dengan implementasi ISampleService di titik akhir dengan WSHttpBinding default (System.ServiceModel.SecurityMode default, yaitu Message), semua pesan dienkripsi dan ditandatangani karena ini adalah tingkat perlindungan default. Namun, ketika layanan ISampleService digunakan dengan BasicHttpBinding default (SecurityMode default, yaitu None), semua pesan dikirim sebagai teks karena tidak ada keamanan untuk pengikatan ini sehingga tingkat perlindungannya diabaikan (yaitu, pesan tidak dienkripsi atau ditandatangani). Jika SecurityMode diubah menjadi Message, maka pesan-pesan ini akan dienkripsi dan ditandatangani (karena itu sekarang akan menjadi tingkat perlindungan default pengikatan).

Jika Anda ingin secara eksplisit menentukan atau menyesuaikan persyaratan perlindungan untuk kontrak Anda, atur properti ProtectionLevel (atau properti ProtectionLevel mana pun pada cakupan yang lebih kecil) ke tingkat yang diperlukan kontrak layanan Anda. Dalam hal ini, menggunakan pengaturan eksplisit memerlukan pengikatan untuk mendukung pengaturan tersebut setidaknya untuk cakupan yang digunakan. Misalnya, contoh kode berikut menetapkan satu nilai ProtectionLevel secara eksplisit, untuk operasi GetGuid.

[ServiceContract]  
public interface IExplicitProtectionLevelSampleService  
{  
  [OperationContractAttribute]  
  public string GetString();  
  
  [OperationContractAttribute(ProtectionLevel=ProtectionLevel.None)]  
  public int GetInt();
  [OperationContractAttribute(ProtectionLevel=ProtectionLevel.EncryptAndSign)]  
  public int GetGuid();
}  

Berikut ini adalah kode Visual Basic yang setara.

<ServiceContract()> _
Public Interface IExplicitProtectionLevelSampleService
    <OperationContract()> _
    Public Function GetString() As String
    End Function
  
    <OperationContract(ProtectionLevel := ProtectionLevel.None)> _
    Public Function GetInt() As Integer
    End Function
  
    <OperationContractAttribute(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
    Public Function GetGuid() As Integer
    End Function
  
End Interface  

Layanan yang menerapkan kontrak IExplicitProtectionLevelSampleService ini dan memiliki titik akhir yang menggunakan WSHttpBinding default (System.ServiceModel.SecurityMode default, yaitu Message) memiliki perilaku berikut:

  • Pesan operasi GetString dienkripsi dan ditandatangani.

  • Pesan operasi GetInt dikirim sebagai teks tidak terenkripsi dan tidak ditandatangani (yaitu, biasa).

  • Operasi GetGuidSystem.Guid dikembalikan dalam pesan yang dienkripsi dan ditandatangani.

Untuk informasi selengkapnya tentang tingkat perlindungan dan cara menggunakannya, lihat Memahami Tingkat Perlindungan. Untuk informasi selengkapnya tentang keamanan, lihat Mengamankan Layanan.

Persyaratan Tanda Tangan Operasi Lainnya

Beberapa fitur aplikasi memerlukan jenis tanda tangan operasi tertentu. Misalnya, pengikatan NetMsmqBinding mendukung layanan dan klien yang tahan lama, di mana aplikasi dapat memulai ulang di tengah komunikasi dan melanjutkan dari tempat terakhirnya tanpa melewatkan pesan apa pun. (Untuk informasi selengkapnya, lihat Antrean di WCF.) Namun, operasi tahan lama hanya boleh menggunakan satu parameter in dan tidak memiliki nilai balik.

Contoh lain adalah penggunaan jenis Stream dalam operasi. Karena parameter Stream mencakup seluruh isi pesan, jika input atau output (yaitu, parameter ref, parameter out, atau nilai pengembalian) berjenis Stream, maka parameter harus menjadi satu-satunya input atau output yang ditentukan dalam operasi Anda. Selain itu, parameter atau jenis hasil harus berupa Stream, System.ServiceModel.Channels.Message, atau System.Xml.Serialization.IXmlSerializable. Untuk informasi selengkapnya tentang aliran, lihat Data Besar dan Aliran.

Nama, Namespace, dan Kebingungan

Nama dan namespace jenis .NET dalam definisi kontrak dan operasi penting ketika kontrak diubah menjadi WSDL dan ketika pesan kontrak dibuat dan dikirim. Oleh karena itu, sangat disarankan agar nama kontrak layanan dan namespace ditetapkan secara eksplisit menggunakan properti Name dan Namespace dari semua atribut kontrak pendukung seperti ServiceContractAttribute, OperationContractAttribute, DataContractAttribute, DataMemberAttribute, dan atribut kontrak lainnya.

Salah satu akibat dari hal ini adalah jika nama dan namespace tidak diatur secara eksplisit, penggunaan pengaburan IL pada perakitan akan mengubah nama jenis kontrak dan namespace dan menghasilkan WSDL yang dimodifikasi dan pertukaran kabel yang biasanya gagal. Jika Anda tidak mengatur nama kontrak dan namespace secara eksplisit tetapi berniat menggunakan pengaburan, gunakan atribut ObfuscationAttribute dan ObfuscateAssemblyAttribute untuk mencegah modifikasi nama dan namespace jenis kontrak.

Lihat juga