Bagikan melalui


Penerapan Versi Layanan

Setelah penyebaran awal, dan berpotensi beberapa kali selama masa pakainya, layanan (dan titik akhir yang diekspos) mungkin perlu diubah karena berbagai alasan, seperti mengubah kebutuhan bisnis, persyaratan teknologi informasi, atau untuk mengatasi masalah lain. Setiap perubahan memperkenalkan versi baru layanan. Topik ini menjelaskan cara mempertimbangkan penerapan versi di Windows Communication Foundation (WCF).

Empat Kategori Perubahan Layanan

Perubahan pada layanan yang mungkin diperlukan dapat diklasifikasikan ke dalam empat kategori:

  • Perubahan kontrak: Misalnya, sebuah operasi mungkin ditambahkan, atau elemen data dalam pesan mungkin ditambahkan atau diubah.

  • Perubahan alamat: Misalnya, layanan berpindah ke lokasi lain di mana titik akhir memiliki alamat baru.

  • Perubahan pengikatan: Misalnya, mekanisme keamanan berubah atau pengaturannya berubah.

  • Perubahan implementasi: Misalnya, saat implementasi metode internal berubah.

Beberapa perubahan ini disebut "breaking" sedangkan yang lainnya "nonbreaking". Perubahan dianggap nonbreaking jika semua pesan yang akan berhasil diproses di versi sebelumnya berhasil diproses dalam versi baru. Setiap perubahan yang tidak memenuhi kriteria tersebut adalah perubahan breaking.

Orientasi dan Penerapan Versi Layanan

Salah satu prinsip orientasi layanan adalah bahwa layanan dan klien bersifat otonom (atau independen). Hal ini menyiratkan bahwa pengembang layanan tidak dapat berasumsi bahwa mereka mengontrol atau bahkan tahu tentang semua klien layanan. Hal ini menghilangkan opsi untuk membangun kembali dan menyebarkan ulang semua klien ketika layanan mengubah versi. Topik ini mengasumsikan layanan mematuhi prinsip ini dan oleh karena itu harus diubah atau "versi" independen dari kliennya.

Dalam kasus di mana perubahan yang melanggar tidak terduga dan tidak dapat dihindari, aplikasi dapat memilih untuk mengabaikan prinsip ini dan mengharuskan klien dibangun kembali dan disebarkan ulang dengan versi baru layanan.

Penerapan Versi Kontrak

Kontrak yang digunakan oleh klien tidak perlu sama dengan kontrak yang digunakan oleh layanan; mereka hanya perlu kompatibel.

Untuk kontrak layanan, kompatibilitas berarti operasi baru yang diekspos oleh layanan dapat ditambahkan, tetapi operasi yang ada tidak dapat dihapus atau diubah secara semantik.

Untuk kontrak data, kompatibilitas berarti definisi jenis skema baru dapat ditambahkan, tetapi definisi jenis skema yang ada tidak dapat diubah dengan cara breaking. Perubahan breaking mungkin termasuk menghapus anggota data atau mengubah jenis data mereka secara tidak kompatibel. Fitur ini mengizinkan beberapa garis lintang pada layanan dalam mengubah versi kontraknya tanpa melakukan breaking pada klien. Dua bagian berikutnya menjelaskan perubahan nonbreaking dan breaking yang dapat dilakukan pada data WCF dan kontrak layanan.

Penerapan Versi Kontrak Data

Bagian ini berkaitan dengan penerapan versi data saat menggunakan kelas DataContractSerializer dan DataContractAttribute.

Penerapan Versi Ketat

Dalam berbagai skenario ketika perubahan versi menjadi masalah, pengembang layanan tidak memiliki kontrol atas klien, oleh karena itu, pengembang layanan tidak dapat membuat asumsi tentang bagaimana mereka akan bereaksi terhadap perubahan dalam XML atau skema pesan. Dalam kasus ini, Anda harus menjamin bahwa pesan baru akan memvalidasi skema lama, karena dua alasan:

  • Klien lama dikembangkan dengan asumsi bahwa skema tidak akan berubah. Mereka mungkin gagal memproses pesan yang tidak pernah mereka rancang.

  • Klien lama dapat melakukan validasi skema aktual terhadap skema lama bahkan sebelum mencoba memproses pesan.

Pendekatan yang direkomendasikan dalam skenario tersebut adalah memperlakukan kontrak data yang ada sebagai “tidak dapat diubah” dan membuat kontrak data baru dengan nama XML unik yang memenuhi syarat. Pengembang layanan kemudian akan menambahkan metode baru ke kontrak layanan yang ada atau membuat kontrak layanan baru dengan metode yang menggunakan kontrak data baru.

Sering kali pengembang layanan perlu menulis beberapa logika bisnis yang harus berjalan dalam semua versi kontrak data ditambah kode bisnis khusus versi untuk setiap versi kontrak data. Lampiran di akhir topik ini menjelaskan bagaimana antarmuka dapat digunakan untuk memenuhi kebutuhan ini.

Penerapan Versi Lax

Dalam banyak skenario lain, pengembang layanan dapat membuat asumsi bahwa menambahkan anggota baru opsional ke kontrak data tidak akan memutus klien yang ada. Langkah ini mengharuskan pengembang layanan untuk menyelidiki apakah klien yang ada tidak melakukan validasi skema dan bahwa mereka mengabaikan anggota data yang tidak diketahui. Dalam skenario ini, dimungkinkan untuk memanfaatkan fitur kontrak data untuk menambahkan anggota baru dengan cara nonbreaking. Pengembang layanan dapat membuat asumsi ini dengan percaya diri jika fitur kontrak data untuk penerapan versi sudah digunakan untuk versi awal layanan.

WCF, ASP.NET Web Services, dan banyak tumpukan layanan Web lainnya mendukung penerapan versi lax: yaitu, mereka tidak melemparkan pengecualian untuk anggota data baru yang tidak diketahui dalam data yang diterima.

Sangat mudah untuk salah memahami bahwa menambahkan anggota baru tidak akan merusak klien yang ada. Jika Anda tidak yakin bahwa semua klien dapat menangani penerapan versi lax, sebaiknya gunakan pedoman penerapan versi yang ketat dan perlakukan kontrak data sebagai tidak dapat diubah.

Untuk panduan terperinci untuk lax dan penerapan versi kontrak data yang ketat, lihat Praktik Terbaik: Penerapan Versi Kontrak Data.

Membedakan antara Jenis Kontrak Data dan .NET

Kelas atau struktur .NET dapat diproyeksikan sebagai kontrak data dengan menerapkan atribut DataContractAttribute ke kelas terkait. Jenis .NET dan proyeksi kontrak datanya adalah dua hal yang berbeda. Dimungkinkan untuk memiliki beberapa jenis .NET dengan proyeksi kontrak data yang sama. Perbedaan ini sangat berguna dalam memungkinkan Anda mengubah jenis .NET sambil mempertahankan kontrak data yang diproyeksikan, sehingga mempertahankan kompatibilitas dengan klien yang ada bahkan dalam artian ketat. Ada dua hal yang harus selalu Anda lakukan untuk mempertahankan perbedaan ini antara jenis .NET dan kontrak data:

  • Tentukan Name dan Namespace. Anda harus selalu menentukan nama dan namespace kontrak data Anda untuk mencegah nama dan namespace layanan jenis .NET Anda terekspos dalam kontrak. Dengan cara ini, jika Anda memutuskan nanti untuk mengubah namespace atau nama jenis .NET, kontrak data Anda tetap sama.

  • Tentukan Name. Anda harus selalu menentukan nama anggota data Anda untuk mencegah nama anggota .NET Anda terekspos dalam kontrak. Dengan cara ini, jika Anda nantinya memutuskan untuk mengubah namespace atau nama jenis .NET, kontrak data Anda tetap sama.

Mengubah atau Menghapus Anggota

Mengubah nama atau jenis data anggota, atau menghapus anggota data merupakan perubahan breaking meskipun penerapan versi lax diizinkan. Jika diperlukan, buat kontrak data baru.

Jika kompatibilitas layanan sangat penting, Anda mungkin mempertimbangkan untuk mengabaikan anggota data yang tidak digunakan dalam kode Anda dan membiarkannya di tempatnya. Jika Anda membagi anggota data menjadi beberapa anggota, Anda mungkin mempertimbangkan untuk meninggalkan anggota yang ada sebagai properti yang dapat melakukan pemisahan dan agregasi ulang yang diperlukan untuk klien tingkat bawah (klien yang tidak ditingkatkan ke versi terbaru).

Demikian pula, perubahan pada nama atau namespace kontrak data melanggar perubahan.

Round-Trip Data yang Tidak Diketahui

Dalam beberapa skenario, ada kebutuhan untuk "round-trip" data yang tidak diketahui yang berasal dari anggota yang ditambahkan dalam versi baru. Misalnya, layanan "versionNew" mengirim data dengan beberapa anggota yang baru ditambahkan ke klien "versionOld". Klien mengabaikan anggota yang baru ditambahkan saat memproses pesan, tetapi mengirim ulang data yang sama, termasuk anggota yang baru ditambahkan, kembali ke layanan versionNew. Skenario umum untuk ini adalah pembaruan data di mana data diambil dari layanan, diubah, dan dikembalikan.

Untuk mengaktifkan round-trip jenis tertentu, jenisnya harus mengimplementasikan antarmuka IExtensibleDataObject. Antarmuka berisi satu properti, ExtensionData yang mengembalikan jenis ExtensionDataObject. Properti ini digunakan untuk menyimpan data apa pun dari versi kontrak data mendatang yang tidak diketahui oleh versi saat ini. Data ini buram untuk klien, tetapi ketika instans diserialisasikan, konten properti ExtensionData ditulis dengan data anggota kontrak data lainnya.

Disarankan agar semua jenis mengimplementasikan antarmuka ini untuk mengakomodasi anggota baru dan yang tidak dikenal di masa mendatang.

Pustaka Kontrak Data

Mungkin ada pustaka kontrak data di mana kontrak diterbitkan ke repositori pusat, serta pelaksana layanan dan jenis menerapkan dan mengekspos kontrak data dari repositori tersebut. Dalam hal ini, ketika Anda menerbitkan kontrak data ke repositori, Anda tidak memiliki kontrol atas siapa yang membuat jenis yang mengimplementasikannya. Dengan demikian, Anda tidak dapat memodifikasi kontrak setelah diterbitkan, perenderan secara efektif menjadikannya tidak dapat diubah.

Saat Menggunakan XmlSerializer

Prinsip penerapan versi yang sama berlaku saat menggunakan kelas XmlSerializer. Saat diperlukan penerapan versi yang ketat, perlakukan kontrak data sebagai tidak dapat diubah dan buat kontrak data baru dengan nama unik dan memenuhi syarat untuk versi baru. Ketika Anda yakin bahwa penerapan versi lax dapat digunakan, Anda dapat menambahkan anggota baru yang dapat diserialisasikan dalam versi baru tetapi tidak mengubah atau menghapus anggota yang ada.

Catatan

XmlSerializer menggunakan atribut XmlAnyElementAttribute dan XmlAnyAttributeAttribute untuk mendukung round-trip data yang tidak diketahui.

Penerapan Versi Kontrak Pesan

Panduan untuk penerapan versi kontrak pesan sangat mirip dengan penerapan versi kontrak data. Jika diperlukan penerapan versi yang ketat, Anda tidak boleh mengubah isi pesan, tetapi sebaliknya, buat kontrak pesan baru dengan nama unik yang memenuhi syarat. Jika Anda tahu bahwa Anda dapat menggunakan penerapan versi lax, Anda dapat menambahkan bagian isi pesan baru tetapi tidak mengubah atau menghapus yang sudah ada. Panduan ini berlaku untuk kontrak pesan kosong dan tersembunyi.

Header pesan selalu dapat ditambahkan, meskipun penerapan versi yang ketat sedang digunakan. Bendera MustUnderstand dapat memengaruhi penerapan versi. Secara umum, model penerapan versi untuk header di WCF seperti yang dijelaskan dalam spesifikasi SOAP.

Penerapan Versi Kontrak Layanan

Mirip dengan penerapan versi kontrak data, penerapan versi kontrak layanan juga melibatkan penambahan, perubahan, dan penghapusan operasi.

Menentukan Nama, Namespace, dan Tindakan

Secara default, nama kontrak layanan adalah nama antarmuka. Namespace defaultnya adalah http://tempuri.org, dan setiap tindakan operasi adalah http://tempuri.org/contractname/methodname. Disarankan agar Anda secara eksplisit menentukan nama dan namespace untuk kontrak layanan, dan tindakan untuk setiap operasi untuk menghindari penggunaan http://tempuri.org dan untuk mencegah nama antarmuka dan metode terekspos dalam kontrak layanan.

Menambahkan Parameter dan Operasi

Menambahkan operasi layanan yang diekspos oleh layanan adalah perubahan yang tidak dapat dipisahkan karena klien yang ada tidak perlu khawatir tentang operasi baru tersebut.

Catatan

Menambahkan operasi ke kontrak panggilan balik dupleks adalah perubahan breaking.

Mengubah Parameter Operasi atau Jenis Pengembalian

Mengubah parameter atau jenis pengembalian umumnya adalah perubahan breaking, kecuali jenis baru tersebut mengimplementasikan kontrak data yang sama seperti yang diterapkan oleh jenis lama. Untuk membuat perubahan seperti itu, tambahkan operasi baru ke kontrak layanan atau tentukan kontrak layanan baru.

Menghapus Operasi

Menghapus operasi juga merupakan perubahan breaking. Untuk membuat perubahan seperti itu, tentukan kontrak layanan baru dan ekspos pada titik akhir baru.

Kontrak Kesalahan

Atribut FaultContractAttribute memungkinkan pengembang kontrak layanan untuk menentukan informasi tentang kesalahan yang dapat dikembalikan dari operasi kontrak.

Daftar kesalahan yang dijelaskan dalam kontrak layanan tidak dianggap lengkap. Kapan saja, operasi dapat mengembalikan kesalahan yang tidak dijelaskan dalam kontraknya. Oleh karena itu mengubah serangkaian kesalahan yang dijelaskan dalam kontrak tidak dianggap sebagai breaking. Misalnya, menambahkan kesalahan baru ke kontrak menggunakan FaultContractAttribute atau menghapus kesalahan yang ada dari kontrak.

Pustaka Kontrak Layanan

Organisasi mungkin memiliki pustaka kontrak di mana kontrak diterbitkan ke repositori pusat dan pelaksana layanan menerapkan kontrak dari repositori tersebut. Dalam hal ini, ketika Anda menerbitkan kontrak data ke repositori, Anda tidak memiliki kontrol atas siapa yang membuat jenis yang mengimplementasikannya. Dengan demikian, Anda tidak dapat memodifikasi kontrak layanan setelah diterbitkan, perenderan secara efektif menjadikannya tidak dapat diubah. WCF mendukung pewarisan kontrak, yang dapat digunakan untuk membuat kontrak baru yang memperpanjang kontrak yang ada. Untuk menggunakan fitur ini, tentukan antarmuka kontrak layanan baru yang mewarisi dari antarmuka kontrak layanan lama, lalu tambahkan metode ke antarmuka baru. Anda kemudian mengubah layanan yang mengimplementasikan kontrak lama untuk mengimplementasikan kontrak baru dan mengubah definisi titik akhir "versionOld" untuk menggunakan kontrak baru. Untuk klien "versionOld", titik akhir akan terus muncul sebagai mengekspos kontrak "versionOld"; untuk klien "versionNew", titik akhir akan muncul untuk mengekspos kontrak "versionNew".

Penerapan Versi Alamat dan Pengikatan

Perubahan pada alamat titik akhir dan pengikatan merupakan perubahan breaking kecuali klien mampu menemukan alamat atau pengikatan titik akhir baru secara dinamis. Salah satu mekanisme untuk menerapkan kemampuan ini adalah dengan menggunakan registri Universal Discovery Description and Integration (UDDI) dan Pola Pemanggilan UDDI di mana klien mencoba berkomunikasi dengan titik akhir dan, setelah kegagalan, meminta registri UDDI yang telah dikenal untuk metadata titik akhir saat ini. Klien kemudian menggunakan alamat dan pengikatan dari metadata ini untuk berkomunikasi dengan titik akhir. Jika komunikasi ini berhasil, klien menyimpan alamat dan informasi pengikatan untuk digunakan di masa mendatang.

Layanan Perutean dan Penerapan Versi

Jika perubahan yang dilakukan pada layanan adalah perubahan breaking dan Anda harus memiliki dua atau lebih versi layanan yang berbeda yang berjalan secara bersamaan, Anda dapat menggunakan Layanan Perutean WCF untuk merutekan pesan ke instans layanan yang sesuai. Layanan Perutean WCF menggunakan perutean berbasis konten, dengan kata lain, layanan ini menggunakan informasi dalam pesan untuk menentukan tempat merutekan pesan. Untuk informasi selengkapnya tentang Layanan Perutean WCF, lihat Layanan Perutean. Untuk contoh cara menggunakan Layanan Perutean WCF untuk penerapan versi layanan, lihat Cara: Penerapan Versi Layanan.

Lampiran

Panduan penerapan versi kontrak data umum saat diperlukan penerapan versi yang ketat adalah memperlakukan kontrak data sebagai tidak dapat diubah dan membuat kontrak yang baru ketika perubahan diperlukan. Kelas baru perlu dibuat untuk setiap kontrak data baru, sehingga diperlukan sebuah mekanisme untuk menghindari keharusan mengambil kode yang ada yang ditulis mengenai kelas kontrak data lama dan menulis ulang tentang kelas kontrak data baru.

Salah satu mekanisme tersebut adalah menggunakan antarmuka untuk menentukan anggota setiap kontrak data dan menulis kode implementasi internal dalam hal antarmuka ketimbang kelas kontrak data yang mengimplementasikan antarmuka. Kode berikut untuk versi 1 dari layanan menunjukkan antarmuka IPurchaseOrderV1 dan PurchaseOrderV1:

public interface IPurchaseOrderV1  
{  
    string OrderId { get; set; }  
    string CustomerId { get; set; }  
}  
  
[DataContract(  
Name = "PurchaseOrder",  
Namespace = "http://examples.microsoft.com/WCF/2005/10/PurchaseOrder")]  
public class PurchaseOrderV1 : IPurchaseOrderV1  
{  
    [DataMember(...)]  
    public string OrderId {...}  
    [DataMember(...)]  
    public string CustomerId {...}  
}  

Sementara operasi kontrak layanan akan ditulis dalam hal PurchaseOrderV1, logika bisnis aktual akan dalam hal IPurchaseOrderV1. Kemudian, di versi 2, akan ada antarmuka IPurchaseOrderV2 baru dan kelas PurchaseOrderV2 baru seperti yang ditunjukkan dalam kode berikut:

public interface IPurchaseOrderV2  
{  
    DateTime OrderDate { get; set; }  
}

[DataContract(
Name = "PurchaseOrder",  
Namespace = "http://examples.microsoft.com/WCF/2006/02/PurchaseOrder")]  
public class PurchaseOrderV2 : IPurchaseOrderV1, IPurchaseOrderV2  
{  
    [DataMember(...)]  
    public string OrderId {...}  
    [DataMember(...)]  
    public string CustomerId {...}  
    [DataMember(...)]  
    public DateTime OrderDate { ... }  
}  

Kontrak layanan akan diperbarui untuk menyertakan operasi baru yang ditulis berkenaan dengan PurchaseOrderV2. Logika bisnis yang ada yang ditulis berkenaan dengan IPurchaseOrderV1 akan terus berfungsi untuk PurchaseOrderV2 dan logika bisnis baru yang membutuhkan properti OrderDate akan ditulis berkenaan dengan IPurchaseOrderV2.

Lihat juga