Ikhtisar: Bagian ini terutama menjelaskan pengecualian dan simulasi pengecualian yang mungkin terjadi dalam panggilan layanan, dan menganalisis kapan dan pengecualian apa yang dapat ditangkap, dan cara meneruskan pengecualian layanan ke klien dengan cara yang benar.
Di akhir artikel, urutan penangkapan untuk pengecualian penangkapan yang benar diberikan. Pengambilan pengecualian ini hanyalah pengenalan, dan beberapa di antaranya adalah fungsi aplikasi, sehingga kode dan penulisannya relatif sederhana. Ini juga memperkenalkan beberapa teknik penanganan pengecualian di sisi server.
1. Pertama, kita buat server dan client kalkulator sederhana, sebagai berikut:
Klik untuk memperluas kode
//Server[ServiceContract]antarmuka publik ICalc{[OperationContract][FaultContract(typeof(GreentingError))]string Div(int x, int y);}kelas publik Calc : ServiceBase, ICalc {public string Div(int x, int y ) ) {hasil string = string.Kosong; coba {hasil = string.Format("hasil: {0}", x / y); catch (DivideByZeroException ex) {throw ex; [Kontrak Layanan] antarmuka publik ICalc { [Kontrak Operasi] [FaultContract(typeof(GreentingError))] string Div(int x, int y } kelas publik CalcClient : ClientBase<ICalc>, ICalc{ public string Div(int x, int y); ) ) {kembalikan basis.Saluran.Div(x, y }}
Oke, saya akui kodenya cukup sederhana, tapi saya suka yang sederhana.
2. Hal-hal sederhana itu baik, dan menyebutnya jauh lebih sederhana;
coba { CalcClientcalcclient = CalcClient() baru; hasil string =calcclient.Div(10, 0); Console.WriteLine(hasil); Console.ReadKey(); catch (TimeoutExceptionex) {throw ex; contoh) {lempar contoh; } tangkapan (FaultExceptionex) {lempar contoh;
3. Saat kita memanggil metode layanan Div(int x, int y) dan meneruskan nilai 0 ke logaritma y, server akan memunculkan pengecualian DivideByZeroException, yang diharapkan. Pada saat ini,
Pengecualian ini tertangkap di bagian FaultException klien.
4. Tidak masalah, kami akan memasukkan FaultException secara manual ke dalam kode server.
catch (DivideByZeroException ex){FaultException pengecualian = new FaultException(ex.Message throw pengecualian;}
Saat ini, saya menemukan bahwa FaultException menangkap pengecualian ini.
5. Lakukan tes lain.
Tambahkan kode ini ke layanan: System.Threading.Thread.Sleep(70000); menyebabkan waktu layanan habis.
Kali ini, TimeOutException akhirnya menangkap pengecualian server, jadi kita harus bertanya, kapan FaultException<GreentingError> akan menangkap pengecualian tersebut? Jawabannya adalah ketika server menampilkan FaultException<GreentingError>, kutip sebuah bagian di MSDN (bagian hijau):
Jika pendengar menerima kesalahan SOAP yang tidak diharapkan atau ditentukan dalam kontrak operasi, objek FaultException akan dilempar. Dua jenis kesalahan SOAP dapat dikirim: dideklarasikan dan tidak dideklarasikan. Kesalahan SOAP yang dinyatakan adalah kesalahan yang operasinya memiliki atribut System.ServiceModel.FaultContractAttribute yang menentukan jenis kesalahan SOAP khusus. Kesalahan SOAP yang tidak dideklarasikan adalah kesalahan yang tidak ditentukan dalam kontrak operasi. "Kesalahan SOAP tak terduga atau tidak ditentukan" di sini mengacu pada jenis kesalahan khusus yang tidak digabungkan dengan FaultContractAttribute dalam operasi layanan.
6. Jadi kapan CommincationException akan ditangkap?
MSDN mengatakan: Aplikasi menangani objek CommunicationException yang mungkin dilempar selama komunikasi
Nah, untuk memunculkan pengecualian ini, kami melakukan hal berikut. Pertama tutup objek saluran saat ini di server.
OperationContext.Saat ini.Saluran.Tutup();
Sayangnya, klien tidak menangkap CommunicationException, namun menangkap TimeOutException! Karena tidak ada pengecualian yang terjadi setelah saluran layanan ditutup, tidak ada pesan yang dikembalikan ke klien. Setelah menunggu selama jangka waktu tertentu, waktu klien habis dan keluar.
Jadi kami menentukan TimeSpan saat menutup saluran. Hal ini memungkinkan panggilan untuk segera kembali. Tentu saja, pengembalian panggilan juga dapat diselesaikan melalui Channel.Abort.
OperationContext.Saat ini.Saluran.Tutup(Rentang Waktu baru(5000));
Saat memanggil metode Tutup IContextChannel, tentukan waktu penyelesaian operasi pengiriman sebelum batas waktu habis, sehingga pesan dapat segera dikembalikan dalam waktu yang ditentukan tanpa harus menunggu panggilan layanan habis, jika tidak, klien pasti akan membuang pengecualian TimeOutException.
7. Solusi
Pada saat yang sama, untuk mengambil beberapa tindakan perbaikan ketika terjadi pengecualian dalam layanan, kami membuat kelas abstrak baru ServiceBase dan menjadikan kelas implementasi layanan Calc mewarisinya, sehingga kami dapat memperoleh kendali atas berbagai transisi status dari layanan. Kelas ServiceBase adalah sebagai berikut:
public abstract parsial class ServiceBase { private IContextChannel channel = null; protected ServiceBase() { channel = OperationContext.Current.Channel;Opening += new EventHandler(delegate(object sender, EventArgs e) {/* TO DO*/ }) ; saluran.Dibuka += EventHandler baru(delegasi(pengirim objek, EventArgs e) {/* YANG HARUS DILAKUKAN*/ }); }); saluran.Tertutup += new EventHandler(delegate(pengirim objek, EventArgs e) { Batalkan(); }); saluran.Faulted += new EventHandler(delegasi(pengirim objek, EventArgs e) { Batalkan(); }) ; } void Buka() {/* UNTUK DILAKUKAN*/ } void Tutup() { /* UNTUK DILAKUKAN*/} void Batalkan() { channel.Batalkan();
Seperti dapat dilihat dari kode di atas, setelah saluran layanan ditutup, kami segera menghentikan layanan dan membiarkan pesan segera kembali. Pada saat ini, meskipun layanan ditutup selama operasi tanpa menentukan waktu penyelesaian batas waktu, panggilan tersebut masih bisa segera kembali.
Kali ini klien akhirnya menangkap CommunicationException, seperti yang ditunjukkan pada gambar di bawah ini:
Mengapa ini terjadi?
8. Mari kita lihat hierarki pewarisan CommunicationException, yang dapat menjadi inspirasi bagi kita.
8.1. Yang pertama adalah hierarki warisan FaultException<TDetail>.
8.2, lagi-lagi hierarki pewarisan TimeOutException.
9. Seperti terlihat pada gambar di atas, TimeOutException dan CommunicationException keduanya mewarisi dari kelas SystemException, sedangkan FaultException mewarisi dari CommunicationException, dan terakhir FaultException<TDetail> mewarisi dari kelas FaultException.
10. Terakhir, kami menyimpulkan bahwa urutan yang benar untuk menangkap pengecualian pada klien adalah:
TimeOutException> FaultException<TDetail> > FaultException > CommunicationException > Pengecualian. Sangat disarankan agar pengembang membuang dan menangkap pengecualian tipe FaultException<TDetail>.
Penulis: Lao Mi Sumber: http://www.cnblogs.com/viter/
Hak cipta artikel ini adalah milik penulis dan Blog Park. Pencetakan ulang diperbolehkan. Namun, pernyataan ini harus disimpan tanpa persetujuan penulis, dan tautan ke teks asli harus disediakan di posisi yang jelas di halaman artikel. hak untuk menuntut tanggung jawab hukum dilindungi undang-undang.