Aracılığıyla paylaş


Hata Gönderme ve Hata Alma

SOAP hataları, bir hizmetten istemciye ve çift yönlü durumda istemciden hizmete birlikte çalışabilir bir şekilde hata durumu bilgilerini aktarır. Genellikle bir hizmet özel hata içeriğini tanımlar ve bunları döndürebilecek işlemleri belirtir. (Daha fazla bilgi için bkz. Hataları Tanımlama ve Belirtme.) Bu konuda, ilgili hata koşulu oluştuğunda bir hizmet veya çift yönlü istemcinin bu hataları nasıl gönderebileceği ve bir istemci veya hizmet uygulamasının bu hataları nasıl işlediği açıklanır. Windows Communication Foundation (WCF) uygulamalarında hata işlemeye genel bakış için bkz. Sözleşmelerde ve Hizmetlerde Hataları Belirtme ve İşleme.

SOAP Hataları Gönderme

Bildirilen SOAP hataları, bir işlemin özel SOAP hata türünü belirttiği System.ServiceModel.FaultContractAttribute'ye sahip olan hatalardır. Bildirilmemiş SOAP hataları, bir işlem için sözleşmede belirtilmeyen hatalardır.

Bildirilen Hataları Gönderme

Bildirilen bir SOAP hatası göndermek için, SOAP hatasının uygun olduğu hata durumunu algılayın ve bu işlem için System.ServiceModel.FaultException<TDetail> içinde belirtilen türde yeni bir nesne tipi parametre olarak atanmış FaultContractAttribute yeni bir nesne fırlatın. Aşağıdaki kod örneği, FaultContractAttribute işleminin, SampleMethod ayrıntı türüyle bir SOAP hatası döndürebileceğini belirtmek için GreetingFault kullanımını gösterir.

[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

Müşteriye hata bilgilerini iletmek için, uygun hata koşulunu yakalayın ve bağımsız değişken olarak yeni bir GreetingFault nesnesiyle yeni bir System.ServiceModel.FaultException<TDetail> türünden GreetingFault oluşturun, aşağıdaki kod örneğinde olduğu gibi. İstemci bir WCF istemci uygulamasıysa, bu durumu türü System.ServiceModel.FaultException<TDetail> olan GreetingFault türünde yönetilen bir özel durum olarak deneyimler.

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

Bildirilmemiş Hatalar Gönderme

Bildirilmemiş hatalar göndermek, WCF uygulamalarında sorunları hızla tanılamak ve hatalarını ayıklamak için çok yararlı olabilir, ancak hata ayıklama aracı olarak kullanışlılığı sınırlıdır. Daha genel olarak, hata ayıklarken ServiceDebugBehavior.IncludeExceptionDetailInFaults özelliğini kullanmanız önerilir. Bu değeri true olarak ayarladığınızda, istemciler FaultException<TDetail> türünde ExceptionDetail özel durumlar olarak bu tür hatalarla karşılaşır.

Önemli

Yönetilen özel durumlar iç uygulama bilgilerini açığa çıkarabileceğinden, ServiceBehaviorAttribute.IncludeExceptionDetailInFaults veya ServiceDebugBehavior.IncludeExceptionDetailInFaults öğelerinin true olarak ayarlanması, WCF istemcilerinin iç hizmet işlemi özel durumları hakkında, kişisel veya diğer hassas bilgiler de dahil olmak üzere, bilgi edinmesine izin verebilir.

Bu nedenle, ServiceBehaviorAttribute.IncludeExceptionDetailInFaults veya ServiceDebugBehavior.IncludeExceptionDetailInFaults değerini true olarak ayarlamak, yalnızca bir hizmet uygulamasında geçici olarak hata ayıklama yöntemi olarak önerilir. Ayrıca, bu şekilde ele alınmayan yönetilen istisnaları döndüren bir yöntemin WSDL'sinde, türü FaultException<TDetail> olan ExceptionDetail için sözleşme bulunmaz. İstemciler, hata ayıklama bilgilerini düzgün bir şekilde almak için bilinmeyen bir SOAP hatası (WCF istemcilerine nesne olarak System.ServiceModel.FaultException döndürülür) olasılığını beklemelidir.

Bildirilmemiş bir SOAP hatası göndermek için bir System.ServiceModel.FaultException nesne (genel tür FaultException<TDetail>değil) oluşturun ve dizeyi oluşturucuya geçirin. Bu, WCF istemci uygulamalarına, System.ServiceModel.FaultException yöntemini çağırarak dizenin kullanılabilir olduğu fırlatılan bir FaultException<TDetail>.ToString istisna olarak sunulur.

Uyarı

Dize türünde bir SOAP hatası bildirir ve ardından tür parametresi FaultException<TDetail> olan hizmetinizde System.String üzerinden bunu atarsanız, dize değeri FaultException<TDetail>.Detail özelliğine atanır ve FaultException<TDetail>.ToString üzerinden kullanılamaz.

Hataları İşleme

WCF istemcilerinde, istemci uygulamalarının ilgilendiği iletişim sırasında oluşan SOAP hataları yönetilen özel durumlar olarak oluşturulur. Herhangi bir programın yürütülmesi sırasında ortaya çıkabilecek birçok özel durum olsa da, WCF istemci programlama modelini kullanan uygulamalar iletişim sonucunda aşağıdaki iki türün özel durumlarını işlemeyi bekleyebilir.

TimeoutException bir işlem belirtilen zaman aşımı süresini aştığında nesneler fırlatılır.

CommunicationException nesneleri, hizmette veya istemcide kurtarılabilir bir iletişim hatası durumu oluştuğunda atılır.

Bu sınıf, CommunicationException iki önemli türetilmiş türe, FaultException ve genel FaultException<TDetail> türe sahiptir.

FaultException İstisnalar, bir dinleyici işlem sözleşmesinde beklenmeyen veya belirtilmeyen bir hata aldığında oluşur; genellikle uygulama hata ayıklanırken ve hizmetin ServiceDebugBehavior.IncludeExceptionDetailInFaults özelliği true olarak ayarlandığında bu durum oluşur.

FaultException<TDetail> İstemci tarafında, işlem sözleşmesinde belirtilen bir hata yanıt olarak alındığında (yani, OperationContractAttribute özniteliği IsOneWay değerine ayarlanmış bir yöntem için), iki yönlü bir işlemde özel durumlar oluşturulur.

Uyarı

Bir WCF hizmetinin ServiceBehaviorAttribute.IncludeExceptionDetailInFaults veya ServiceDebugBehavior.IncludeExceptionDetailInFaults özelliği true olarak ayarlandığında, istemci bunu türü FaultException<TDetail> olan bildirilmeyen bir ExceptionDetail olarak deneyimler. İstemciler bu özel hatayı yakalayabilir veya FaultException için bir catch bloğunda hatayı işleyebilir.

Genellikle yalnızca FaultException<TDetail>, TimeoutException ve CommunicationException istisnaları, müşterilerin ve hizmetlerin ilgisini çeker.

Uyarı

Tabii ki diğer istisnalar da meydana gelebilir. Beklenmeyen özel durumlar, System.OutOfMemoryException gibi yıkıcı hataları içerir: Genellikle uygulamalar bu tür özel durumları yakalamamalıdır.

Hata İstisnalarını Doğru Sırada Yakalayın

FaultException<TDetail> FaultException'den türetildiğinden ve FaultExceptionCommunicationException'den türetildiğinden, bu istisnaları uygun sırada yakalamak önemlidir. Örneğin, ilk yakaladığınız CommunicationException bir try/catch bloğunuz varsa, tüm belirtilen ve belirtilmeyen SOAP hataları orada işlenir; özel FaultException<TDetail> durumu işlemek için sonraki yakalama blokları hiçbir zaman çağrılmaz.

Bir işlemin belirtilen sayıda hata döndürebileceğini unutmayın. Her hata benzersiz bir türdür ve ayrı ayrı işlenmelidir.

Kanalı Kapatırken İstisnaları İşleme

Yukarıdaki tartışmaların çoğunun uygulama iletilerini işleme sırasında gönderilen hatalarla, yani istemci uygulaması WCF istemci nesnesindeki işlemleri çağırdığında açıkça istemci tarafından gönderilen iletilerle ilgili olması gerekir.

Yerel nesnelerle bile nesnenin imha edilmesi, geri dönüşüm süreci sırasında meydana gelen özel durumları tetikleyebilir veya maskeleyebilir. WCF istemci nesnelerini kullandığınızda benzer bir şey oluşabilir. İşlemleri çağırdığınızda, kurulan bir bağlantı üzerinden ileti gönderirsiniz. Tüm işlemler düzgün çalışsa bile, bağlantı temiz bir şekilde kapatılamıyorsa veya zaten kapalıysa kanalın kapatılması istisnalara neden olabilir.

İstemci nesne kanalları genellikle aşağıdaki yollardan biriyle kapatılır:

  • WCF istemci nesnesi geri dönüştürüldiğinde.

  • Müşteri uygulaması ClientBase<TChannel>.Close çağırdığında.

  • Müşteri uygulaması ICommunicationObject.Close çağırdığında.

  • İstemci uygulaması bir oturum için sonlandırıcı işlem olan bir işlemi çağırdığında.

Her durumda, kanalı kapatmak, kanala uygulama düzeyinde karmaşık işlevleri desteklemek üzere ileti gönderebilecek temel kanalları kapatmaya başlamasını ister. Örneğin, bir sözleşme oturum gerektiriyorsa, bir bağlayıcı bir oturum oluşturmak için hizmet kanalıyla ileti alışverişi yaparak oturum oluşturmaya çalışır. Kanal kapatıldığında, temel alınan oturum kanalı hizmete oturumun sonlandırıldığını bildirir. Bu durumda, kanal zaten durdurulduysa, kapatıldıysa veya başka bir şekilde kullanılamıyorsa (örneğin, bir ağ kablosu takılı olmadığında), istemci kanalı hizmet kanalına oturumun sonlandırıldığını ve bir özel durumun neden olabileceğini bildiremez.

Gerekirse Kanalı Durdur

Kanalı kapatmanın istisnalar meydana getirebileceğinden, hata istisnalarını doğru sırada yakalamanın yanı sıra, çağrı yaparken kullanılan kanalın yakalama bloğunda iptal edilmesinin önemli olduğu önerilir.

Hata bir işleme özgü hata bilgilerini iletirse ve başkalarının bunu kullanabilmesi mümkün olmaya devam ederse, kanalı durdurmanız gerekmez (bu durumlar nadir olsa da). Diğer tüm durumlarda, kanalı durdurmanız önerilir. Bu noktaların tümünü gösteren bir örnek için bkz. Beklenen Özel Durumlar.

Aşağıdaki kod örneğinde, bildirilen bir hata ve bildirilmemiş hata dahil olmak üzere temel bir istemci uygulamasında SOAP hata özel durumlarının nasıl işlendiği gösterilmektedir.

Uyarı

Bu örnek kod yapısını kullanmaz using . Kapatma kanalları özel durumlar oluşturabileceğinden, uygulamaların önce bir WCF istemcisi oluşturması ve ardından aynı deneme bloğunda WCF istemcisini açması, kullanması ve kapatması önerilir. Ayrıntılar için bkz . WCF İstemcisine Genel Bakış ve WCF istemci kaynaklarını serbest bırakmak için Kapat ve Durdur'u kullanma.

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

Ayrıca bakınız