Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Sampel AdvancedDispatchByBody menunjukkan cara menerapkan algoritma alternatif untuk menetapkan pesan masuk ke operasi.
Secara default, dispatcher model layanan memilih metode penanganan yang sesuai untuk pesan masuk berdasarkan header "Tindakan" WS-Addressing pesan atau informasi yang setara dalam permintaan HTTP SOAP.
Beberapa stack layanan Web SOAP 1.1 yang tidak mengikuti panduan WS-I Profil Dasar 1.1 tidak mengirimkan pesan berdasarkan Action URI, melainkan berdasarkan nama XML yang memenuhi syarat dari elemen pertama di dalam badan SOAP. Demikian juga, sisi klien dari tumpukan ini mungkin mengirimkan pesan dengan penanda HTTP SoapAction yang kosong atau sewenang-wenang, sebagaimana diizinkan oleh spesifikasi SOAP 1.1.
Untuk mengubah cara pesan dikirim ke metode, sampel mengimplementasikan IDispatchOperationSelector antarmuka ekstensibilitas pada DispatchByBodyElementOperationSelector. Kelas ini memilih operasi berdasarkan elemen pertama isi pesan.
Konstruktor kelas mengharapkan kamus yang diisi dengan pasangan XmlQualifiedName dan string, di mana nama yang teridentifikasi secara tepat menunjukkan nama elemen pertama dari tubuh SOAP dan string menunjukkan nama operasi yang sesuai.
defaultOperationName adalah nama operasi yang menerima semua pesan yang tidak dapat dicocokkan dengan kamus ini:
class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
{
Dictionary<XmlQualifiedName, string> dispatchDictionary;
string defaultOperationName;
public DispatchByBodyElementOperationSelector(Dictionary<XmlQualifiedName,string> dispatchDictionary, string defaultOperationName)
{
this.dispatchDictionary = dispatchDictionary;
this.defaultOperationName = defaultOperationName;
}
}
IDispatchOperationSelector implementasi sangat mudah untuk dibangun karena hanya ada satu metode pada antarmuka: SelectOperation. Pekerjaan metode ini adalah memeriksa pesan masuk dan mengembalikan string yang sama dengan nama metode pada kontrak layanan untuk titik akhir saat ini.
Dalam sampel ini, pemilih operasi memperoleh XmlDictionaryReader untuk isi pesan masuk menggunakan GetReaderAtBodyContents. Metode ini telah menempatkan pembaca pada elemen pertama dari badan pesan sehingga memungkinkan untuk mendapatkan nama elemen saat ini dan URI namespace serta menggabungkannya ke dalam XmlQualifiedName yang kemudian digunakan untuk mencari operasi yang sesuai dari kamus yang dipegang oleh pemilih operasi.
public string SelectOperation(ref System.ServiceModel.Channels.Message message)
{
XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
XmlQualifiedName lookupQName = new
XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);
message = CreateMessageCopy(message,bodyReader);
if (dispatchDictionary.ContainsKey(lookupQName))
{
return dispatchDictionary[lookupQName];
}
else
{
return defaultOperationName;
}
}
Mengakses isi pesan dengan GetReaderAtBodyContents atau metode lain yang menyediakan akses ke konten isi pesan menyebabkan pesan ditandai sebagai "baca", yang berarti bahwa pesan tidak valid untuk pemrosesan lebih lanjut. Oleh karena itu, pemilih operasi membuat salinan pesan masuk dengan metode yang ditunjukkan dalam kode berikut. Karena posisi pembaca belum diubah selama inspeksi, posisi tersebut dapat direferensikan oleh pesan yang baru dibuat di mana properti pesan dan header pesan juga disalin, yang menghasilkan klon yang tepat dari pesan asli:
private Message CreateMessageCopy(Message message,
XmlDictionaryReader body)
{
Message copy = Message.CreateMessage(message.Version,message.Headers.Action,body);
copy.Headers.CopyHeaderFrom(message,0);
copy.Properties.CopyProperties(message.Properties);
return copy;
}
Menambahkan Pemilih Operasi ke Layanan
Pemilih operasi pengiriman layanan merupakan ekstensi dari dispatcher Windows Communication Foundation (WCF). Untuk memilih metode pada saluran panggilan balik kontrak dupleks, ada juga pemilih operasi klien, yang berfungsi mirip dengan pemilih operasi pengiriman pesan yang dijelaskan di sini, tetapi yang tidak dijelaskan secara langsung dalam contoh ini.
Seperti kebanyakan ekstensi model layanan, pemilih operasi pengiriman ditambahkan ke dispatcher dengan menggunakan perilaku. Perilaku aplikasi adalah objek konfigurasi yang menambahkan satu atau beberapa ekstensi ke runtime pemrosesan (atau ke runtime klien) atau mengubah pengaturannya.
Karena pemilih operasi memiliki cakupan kontrak, perilaku yang sebaiknya diterapkan di sini adalah IContractBehavior. Karena antarmuka diimplementasikan pada kelas turunan seperti yang Attribute ditunjukkan dalam kode berikut, perilaku dapat ditambahkan secara deklaratif ke kontrak layanan apa pun. Setiap kali sebuah ServiceHost dibuka dan runtime pengiriman dibentuk, semua perilaku yang ditemukan baik sebagai atribut pada kontrak, operasi, dan implementasi layanan atau sebagai elemen di dalam konfigurasi layanan ditambahkan secara otomatis dan kemudian diminta untuk memberikan kontribusi ekstensi atau memodifikasi konfigurasi default.
Untuk singkatnya, cuplikan kode berikut hanya menunjukkan implementasi metode ApplyDispatchBehavior, yang mempengaruhi perubahan konfigurasi untuk dispatcher dalam sampel ini. Metode lain tidak ditampilkan karena mereka kembali ke pemanggil tanpa melakukan pekerjaan apa pun.
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]
class DispatchByBodyElementBehaviorAttribute : Attribute, IContractBehavior
{
// public void AddBindingParameters(...)
// public void ApplyClientBehavior(...)
// public void Validate(...)
Pertama, ApplyDispatchBehavior implementasi menyiapkan kamus untuk pencarian pemilih operasi dengan mengulangi elemen-elemen OperationDescription di titik akhir ContractDescription layanan. Kemudian, setiap deskripsi operasi diperiksa untuk perilaku DispatchBodyElementAttribute, sebuah implementasi IOperationBehavior yang juga didefinisikan dalam sampel ini. Meskipun kelas ini juga merupakan perilaku, kelas ini pasif dan tidak secara aktif berkontribusi pada perubahan konfigurasi apa pun pada runtime pengiriman. Semua metodenya mengembalikan kontrol ke pemanggil tanpa melakukan tindakan apa pun. Perilaku operasi hanya ada sehingga metadata yang diperlukan untuk mekanisme pengiriman baru, yaitu nama elemen isi yang memenuhi syarat, yang dipilih berdasarkan kemunculannya, dapat diasosiasikan dengan operasi terkait.
Jika perilaku seperti itu ditemukan, pasangan nilai yang dibuat dari nama (QName properti) yang memenuhi syarat XML dan nama operasi (Name properti) ditambahkan ke kamus.
Setelah kamus diisi, sebuah DispatchByBodyElementOperationSelector baru dibangun dengan informasi ini dan ditetapkan sebagai pemilih operasi dari runtime pengiriman.
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
Dictionary<XmlQualifiedName,string> dispatchDictionary =
new Dictionary<XmlQualifiedName,string>();
foreach( OperationDescription operationDescription in
contractDescription.Operations )
{
DispatchBodyElementAttribute dispatchBodyElement =
operationDescription.Behaviors.Find<DispatchBodyElementAttribute>();
if ( dispatchBodyElement != null )
{
dispatchDictionary.Add(dispatchBodyElement.QName,
operationDescription.Name);
}
}
dispatchRuntime.OperationSelector =
new DispatchByBodyElementOperationSelector(
dispatchDictionary,
dispatchRuntime.UnhandledDispatchOperation.Name);
}
}
Menerapkan Layanan
Perilaku yang diterapkan dalam sampel ini secara langsung memengaruhi bagaimana pesan dari kawat ditafsirkan dan dikirim, yang merupakan fungsi dari kontrak layanan. Akibatnya, perilaku harus dinyatakan pada tingkat kontrak layanan dalam implementasi layanan apa pun yang memilih untuk menggunakannya.
Contoh layanan proyek menerapkan DispatchByBodyElementBehaviorAttribute perilaku kontrak ke IDispatchedByBody kontrak layanan dan melabeli masing-masing dari dua operasi OperationForBodyA() dan OperationForBodyB() dengan DispatchBodyElementAttribute perilaku operasi. Ketika host layanan untuk layanan yang mengimplementasikan kontrak ini dibuka, metadata ini diambil oleh pembuat dispatcher seperti yang dijelaskan sebelumnya.
Karena pemilih operasi dikirim hanya berdasarkan elemen isi pesan dan mengabaikan "Tindakan", diperlukan untuk memberi tahu runtime untuk tidak memeriksa header "Tindakan" pada balasan yang dikembalikan dengan menetapkan wildcard "*" ke ReplyAction properti OperationContractAttribute. Selain itu, diperlukan adanya operasi default yang memiliki properti "Tindakan" yang diatur ke wildcard "*". Operasi default menerima semua pesan yang tidak dapat dikirim dan tidak memiliki DispatchBodyElementAttribute:
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples"),
DispatchByBodyElementBehavior]
public interface IDispatchedByBody
{
[OperationContract(ReplyAction="*"),
DispatchBodyElement("bodyA","http://tempuri.org")]
Message OperationForBodyA(Message msg);
[OperationContract(ReplyAction = "*"),
DispatchBodyElement("bodyB", "http://tempuri.org")]
Message OperationForBodyB(Message msg);
[OperationContract(Action="*", ReplyAction="*")]
Message DefaultOperation(Message msg);
}
Implementasi layanan sampel sangat mudah. Setiap metode membungkus pesan yang diterima ke dalam pesan balasan dan menggemakannya kembali ke klien.
Menjalankan dan Membangun Sampel
Saat Anda menjalankan sampel, konten isi respons operasi ditampilkan di jendela konsol klien yang mirip dengan output (diformat) berikut.
Klien mengirim tiga pesan ke layanan yang elemen konten isinya diberi nama bodyA, , bodyBdan bodyX, masing-masing. Seperti yang dapat disimpulkan dari deskripsi sebelumnya dan kontrak layanan yang ditampilkan, pesan masuk dengan elemen bodyA dikirim ke metode OperationForBodyA(). Karena tidak ada target pengiriman eksplisit untuk pesan dengan bodyX elemen isi, pesan dikirim ke DefaultOperation(). Setiap operasi layanan membungkus isi pesan yang diterima ke dalam elemen khusus untuk metode dan mengembalikannya, yang dilakukan untuk menghubungkan pesan input dan output dengan jelas untuk sampel ini:
<?xml version="1.0" encoding="IBM437"?>
<replyBodyA xmlns="http://tempuri.org">
<q:bodyA xmlns:q="http://tempuri.org">test</q:bodyA>
</replyBodyA>
<?xml version="1.0" encoding="IBM437"?>
<replyBodyB xmlns="http://tempuri.org">
<q:bodyB xmlns:q="http://tempuri.org">test</q:bodyB>
</replyBodyB>
<?xml version="1.0" encoding="IBM437"?>
<replyDefault xmlns="http://tempuri.org">
<q:bodyX xmlns:q="http://tempuri.org">test</q:bodyX>
</replyDefault>
Untuk menyiapkan, mengompilasi, dan menjalankan sampel
Pastikan Anda telah melakukan Prosedur Penyiapan One-Time untuk Sampel Windows Communication Foundation.
Untuk membangun solusi, ikuti instruksi dalam Membangun Sampel Windows Communication Foundation.
Untuk menjalankan sampel dalam konfigurasi satu atau lintas komputer, ikuti instruksi di Menjalankan Sampel Windows Communication Foundation.