Bagikan melalui


Menerima dan Mengirim Kesalahan

Kegagalan SOAP menyampaikan informasi kondisi kesalahan dari layanan ke klien dan dalam kasus dupleks dari klien ke layanan dengan cara yang dapat dioperasikan. Biasanya layanan mendefinisikan konten kesalahan kustom dan menentukan operasi mana yang dapat mengembalikannya. (Untuk informasi selengkapnya, baca Mendefinisikan dan Menentukan Kegagalan.) Topik ini membahas cara layanan atau klien dupleks dapat mengirim kegagalan tersebut ketika kondisi kesalahan yang sesuai telah terjadi dan cara klien atau aplikasi layanan menangani kegagalan ini. Untuk ringkasan penanganan kesalahan dalam aplikasi Windows Communication Foundation (WCF), lihat Menentukan dan Menangani Kesalahan dalam Kontrak dan Layanan.

Mengirim kegagalan SOAP

Kegagalan SOAP yang dideklarasikan adalah kegagalan ketika operasi memiliki System.ServiceModel.FaultContractAttribute yang menentukan jenis kesalahan SOAP kustom. Kegagalan SOAP yang tidak dideklarasikan adalah kegagalan yang tidak ditentukan dalam kontrak untuk suatu operasi.

Mengirim Kegagalan yang Dideklarasikan

Untuk mengirim kegagalan SOAP yang dideklarasikan, deteksi kondisi kesalahan yang sesuai dengan kesalahan SOAP dan tampilkan System.ServiceModel.FaultException<TDetail> baru ketika parameter jenis adalah objek baru dari jenis yang ditentukan dalam FaultContractAttribute untuk operasi itu. Contoh kode berikut menunjukkan penggunaan FaultContractAttribute untuk menentukan bahwa operasi SampleMethod dapat mengembalikan kegagalan SOAP dengan jenis detail GreetingFault.

[OperationContract]
[FaultContractAttribute(
  typeof(GreetingFault),
  Action="http://www.contoso.com/GreetingFault",
  ProtectionLevel=ProtectionLevel.EncryptAndSign
  )]
string SampleMethod(string msg);
<OperationContract, FaultContractAttribute(GetType(GreetingFault), Action:="http://www.contoso.com/GreetingFault", ProtectionLevel:=ProtectionLevel.EncryptAndSign)> _
Function SampleMethod(ByVal msg As String) As String

Untuk menyampaikan informasi kesalahan GreetingFault kepada klien, tangkap kondisi kesalahan yang sesuai dan tampilkan System.ServiceModel.FaultException<TDetail> jenis GreetingFault baru dengan objek GreetingFault baru sebagai argumen, seperti pada contoh kode berikut. Jika klien adalah aplikasi klien WCF, klien tersebut mengalami ini sebagai pengecualian terkelola ketika jenisnya adalah System.ServiceModel.FaultException<TDetail> dari jenis GreetingFault.

throw new FaultException<GreetingFault>(new GreetingFault("A Greeting error occurred. You said: " + msg));
    Throw New FaultException(Of GreetingFault)(New GreetingFault("A Greeting error occurred. You said: " & msg))
End If

Mengirim Kegagalan yang Tidak Dideklarasikan

Mengirim kegagalan yang tidak dideklarasikan bisa sangat berguna untuk mendiagnosis dan men-debug masalah dalam aplikasi WCF dengan cepat, tetapi kegunaannya sebagai alat penelusuran kesalahan terbatas. Secara umum, saat Anda men-debug disarankan agar Anda menggunakan properti ServiceDebugBehavior.IncludeExceptionDetailInFaults. Saat Anda mengatur nilai ini ke true, klien mengalami kegagalan seperti FaultException<TDetail> pengecualian jenis ExceptionDetail.

Penting

Karena pengecualian terkelola dapat mengekspos informasi aplikasi internal, mengatur ServiceBehaviorAttribute.IncludeExceptionDetailInFaults atau ServiceDebugBehavior.IncludeExceptionDetailInFaults ke true dapat mengizinkan klien WCF untuk memperoleh informasi tentang pengecualian operasi layanan internal, termasuk informasi identitas pribadi atau informasi sensitif lainnya.

Oleh karena itu, mengatur ServiceBehaviorAttribute.IncludeExceptionDetailInFaults atau ServiceDebugBehavior.IncludeExceptionDetailInFaults ke true hanya disarankan sebagai cara untuk men-debug aplikasi layanan untuk sementara. Selain itu, WSDL untuk metode yang mengembalikan pengecualian terkelola yang tidak ditangani dengan cara ini tidak berisi kontrak untuk FaultException<TDetail> jenis ExceptionDetail. Klien harus mengharapkan kemungkinan kegagalan SOAP yang tidak diketahui (dikembalikan ke klien WCF sebagai objek System.ServiceModel.FaultException) untuk mendapatkan informasi debug dengan benar.

Untuk mengirim kegagalan SOAP yang tidak dideklarasikan, tampilkan objek System.ServiceModel.FaultException (yaitu, bukan jenis generik FaultException<TDetail>) dan teruskan string ke konstruktor. String ini diekspos ke aplikasi klien WCF sebagai pengecualian System.ServiceModel.FaultException yang ditampilkan ketika string tersedia dengan memanggil metode FaultException<TDetail>.ToString.

Catatan

Jika Anda mendeklarasikan kegagalan SOAP dari string jenis, dan kemudian menampilkannya ke layanan Anda sebagai FaultException<TDetail> ketika parameter jenis adalah System.String nilai string ditetapkan ke properti FaultException<TDetail>.Detail, dan tidak tersedia dari FaultException<TDetail>.ToString.

Menangani Kegagalan

Di klien WCF, kegagalan SOAP yang terjadi selama komunikasi yang menarik bagi aplikasi klien dimunculkan sebagai pengecualian terkelola. Meskipun ada banyak pengecualian yang dapat terjadi selama eksekusi program apa pun, aplikasi yang menggunakan model pemrograman klien WCF diharapkan dapat menangani pengecualian dari dua jenis berikut sebagai hasil komunikasi.

TimeoutException objek ditampilkan saat operasi melebihi periode waktu habis yang ditentukan.

CommunicationException objek ditampilkan ketika ada beberapa kondisi kesalahan komunikasi yang dapat dipulihkan pada layanan atau klien.

Kelas CommunicationException memiliki dua jenis turunan penting, FaultException dan jenis FaultException<TDetail> generik.

FaultException pengecualian ditampilkan ketika pendengar menerima kegagalan yang tidak diharapkan atau ditentukan dalam kontrak operasi; biasanya ini terjadi saat aplikasi sedang di-debug dan layanan memiliki properti ServiceDebugBehavior.IncludeExceptionDetailInFaults yang atur menjadi true.

FaultException<TDetail> pengecualian ditampilkan pada klien saat kegagalan yang ditentukan dalam kontrak operasi diterima sebagai respons terhadap operasi dua arah (yaitu, metode dengan atribut OperationContractAttribute dengan IsOneWay diatur menjadi false).

Catatan

Ketika layanan WCF memiliki properti ServiceBehaviorAttribute.IncludeExceptionDetailInFaults atau ServiceDebugBehavior.IncludeExceptionDetailInFaults yang diatur menjadi true, klien mengalami ini sebagai FaultException<TDetail> jenis ExceptionDetail yang tidak dideklarasikan. Klien dapat menangkap kegagalan khusus ini atau menangani kegagalan dalam blok tangkap untuk FaultException.

Biasanya, hanya pengecualian FaultException<TDetail>, TimeoutException, dan CommunicationException yang menarik bagi klien dan layanan.

Catatan

Pengecualian lain, tentu saja, memang terjadi. Pengecualian yang tidak terduga termasuk kegagalan bencana seperti System.OutOfMemoryException; biasanya aplikasi tidak boleh menangkap metode seperti itu.

Tangkap Pengecualian Kegagalan dalam Urutan yang Benar

Karena FaultException<TDetail> berasal dari FaultException, dan FaultException berasal dari CommunicationException, penting untuk menangkap pengecualian ini dalam urutan yang benar. Jika, misalnya, Anda memiliki blok coba/tangkap di mana Anda pertama kali menangkap CommunicationException, semua kegagalan SOAP yang ditentukan dan tidak ditentukan ditangani di sana; setiap blok tangkapan berikutnya untuk menangani pengecualian FaultException<TDetail> kustom tidak pernah dipanggil.

Ingatlah bahwa satu operasi dapat mengembalikan sejumlah kegagalan yang ditentukan. Setiap kegagalan adalah jenis yang unik dan harus ditangani secara terpisah.

Menangani Pengecualian Saat Menutup Saluran

Sebagian besar diskusi sebelumnya berkaitan dengan kegagalan yang dikirim selama pemrosesan pesan aplikasi, yaitu, pesan yang dikirim secara eksplisit oleh klien saat aplikasi klien memanggil operasi pada objek klien WCF.

Bahkan dengan objek lokal yang membuang objek tersebut dapat meningkatkan atau menutupi pengecualian yang terjadi selama proses daur ulang. Hal serupa dapat terjadi saat Anda menggunakan objek klien WCF. Saat Anda memanggil operasi, Anda mengirim pesan melalui koneksi yang telah dibuat. Menutup saluran dapat menimbulkan pengecualian jika koneksi tidak dapat ditutup dengan rapi atau sudah ditutup, bahkan jika semua operasi dikembalikan dengan benar.

Biasanya, saluran objek klien ditutup dengan salah satu cara berikut:

Dalam semua kasus, menutup saluran menginstruksikan saluran untuk mulai menutup saluran dasar yang mungkin mengirim pesan untuk mendukung fungsionalitas kompleks di tingkat aplikasi. Misalnya, ketika kontrak memerlukan sesi, upaya pengikatan untuk membuat sesi dengan bertukar pesan dengan saluran layanan hingga sesi dibuat. Ketika saluran ditutup, saluran sesi yang mendasari memberi tahu layanan bahwa sesi dihentikan. Dalam hal ini, jika saluran telah dibatalkan, ditutup, atau tidak dapat digunakan (misalnya, ketika kabel jaringan dicabut), saluran klien tidak dapat memberi tahu saluran layanan bahwa sesi dihentikan dan pengecualian dapat terjadi.

Batalkan Saluran Jika Perlu

Karena menutup saluran juga dapat membuang pengecualian, maka, direkomendasikan bahwa selain menangkap pengecualian kegagalan dalam urutan yang benar, penting untuk membatalkan saluran yang digunakan dalam membuat panggilan di blok tangkapan.

Jika kegagalan menyampaikan informasi kesalahan khusus untuk suatu operasi dan tetap memungkinkan orang lain dapat menggunakannya, tidak perlu membatalkan saluran (walaupun kasus ini jarang terjadi). Dalam semua kasus lain, Anda disarankan untuk membatalkan saluran. Untuk contoh yang menunjukkan semua poin ini, baca Pengecualian yang Diharapkan.

Contoh kode berikut menunjukkan cara menangani pengecualian kegagalan SOAP dalam aplikasi klien dasar, termasuk kegagalan yang dideklarasikan dan kegagalan yang tidak dideklarasikan.

Catatan

Kode contoh ini tidak menggunakan konstruksi using. Karena menutup saluran dapat menimbulkan pengecualian, disarankan agar aplikasi membuat klien WCF terlebih dahulu, lalu membuka, menggunakan, dan menutup klien WCF di blok percobaan yang sama. Untuk detailnya, baca Ringkasan Klien WCF dan Gunakan Tutup dan Batalkan untuk melepaskan sumber daya klien WCF.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;

public class Client
{
  public static void Main()
  {
    // Picks up configuration from the config file.
    SampleServiceClient wcfClient = new SampleServiceClient();
    try
    {
      // Making calls.
      Console.WriteLine("Enter the greeting to send: ");
      string greeting = Console.ReadLine();
      Console.WriteLine("The service responded: " + wcfClient.SampleMethod(greeting));

      Console.WriteLine("Press ENTER to exit:");
      Console.ReadLine();

      // Done with service.
      wcfClient.Close();
      Console.WriteLine("Done!");
    }
    catch (TimeoutException timeProblem)
    {
      Console.WriteLine("The service operation timed out. " + timeProblem.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException<GreetingFault> greetingFault)
    {
      Console.WriteLine(greetingFault.Detail.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException unknownFault)
    {
      Console.WriteLine("An unknown exception was received. " + unknownFault.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (CommunicationException commProblem)
    {
      Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
      Console.ReadLine();
      wcfClient.Abort();
    }
  }
}

Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation

Public Class Client
    Public Shared Sub Main()
        ' Picks up configuration from the config file.
        Dim wcfClient As New SampleServiceClient()
        Try
            ' Making calls.
            Console.WriteLine("Enter the greeting to send: ")
            Dim greeting As String = Console.ReadLine()
            Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))

            Console.WriteLine("Press ENTER to exit:")
            Console.ReadLine()

            ' Done with service. 
            wcfClient.Close()
            Console.WriteLine("Done!")
        Catch timeProblem As TimeoutException
            Console.WriteLine("The service operation timed out. " & timeProblem.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch greetingFault As FaultException(Of GreetingFault)
            Console.WriteLine(greetingFault.Detail.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch unknownFault As FaultException
            Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch commProblem As CommunicationException
            Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
            Console.ReadLine()
            wcfClient.Abort()
        End Try
    End Sub
End Class

Lihat juga