Sdílet prostřednictvím


Chyby odesílání a přijímání

Chyby PROTOKOLU SOAP sdělují informace o chybovém stavu ze služby klientovi a v duplexním případě z klienta do služby interoperabilním způsobem. Služba obvykle definuje vlastní obsah selhání a určuje, které operace je můžou vrátit. (Další informace najdete v tématu Definování a určení chyb.) Toto téma popisuje, jak může služba nebo duplexní klient tyto chyby odeslat, když došlo k příslušné chybové podmínce a jak klient nebo aplikace služby tyto chyby zpracovává. Přehled zpracování chyb v aplikacích WCF (Windows Communication Foundation) naleznete v tématu Určení a zpracování chyb v kontraktech a službách.

Odesílání chyb PROTOKOLU SOAP

Deklarované chyby PROTOKOLU SOAP jsou chyby, ve kterých má operace System.ServiceModel.FaultContractAttribute vlastní typ chyby SOAP. Nedelarované chyby PROTOKOLU SOAP jsou chyby, které nejsou zadány ve smlouvě pro operaci.

Odesílání deklarovaných chyb

Chcete-li odeslat deklarovanou chybu SOAP, detekujte chybovou podmínku, pro kterou je chyba SOAP vhodná, a vyvoláte novou System.ServiceModel.FaultException<TDetail> , kde parametr typu je nový objekt typu zadaný v FaultContractAttribute dané operaci. Následující příklad kódu ukazuje použití FaultContractAttribute k určení, že SampleMethod operace může vrátit chybu SOAP s typem podrobností 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

Chcete-li sdělit GreetingFault informace o chybě klientovi, zachyťte odpovídající chybový stav a jako argument vyvoláte nový System.ServiceModel.FaultException<TDetail> typ GreetingFault s novým GreetingFault objektem, jako v následujícím příkladu kódu. Pokud je klient klient klientem klientská aplikace WCF, dojde k tomu jako spravovaná výjimka, kdy je System.ServiceModel.FaultException<TDetail> typ typu 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

Odesílání nedelarovaných chyb

Odesílání nedelarovaných chyb může být velmi užitečné k rychlé diagnostice a ladění problémů v aplikacích WCF, ale jeho užitečnost jako nástroj pro ladění je omezená. Obecně platí, že při ladění se doporučuje použít ServiceDebugBehavior.IncludeExceptionDetailInFaults vlastnost. Když nastavíte tuto hodnotu na true, klienti mají takové chyby jako FaultException<TDetail> výjimky typu ExceptionDetail.

Důležité

Vzhledem k tomu, že spravované výjimky můžou zpřístupnit interní informace o aplikaci, nastavení ServiceBehaviorAttribute.IncludeExceptionDetailInFaults nebo ServiceDebugBehavior.IncludeExceptionDetailInFaultstrue umožnit klientům WCF získat informace o výjimkách operací interní služby, včetně identifikovatelných osobních nebo jiných citlivých informací.

Proto se nastavení ServiceBehaviorAttribute.IncludeExceptionDetailInFaults nebo ServiceDebugBehavior.IncludeExceptionDetailInFaults nastavení true doporučuje pouze jako způsob dočasného ladění aplikace služby. Kromě toho WSDL pro metodu, která vrací neošetřené spravované výjimky tímto způsobem neobsahuje kontrakt pro FaultException<TDetail> typ ExceptionDetail. Klienti musí očekávat, že je možné správně získat informace o ladění neznámou chybou SOAP (vrácenou klientům WCF jako System.ServiceModel.FaultException objekty).

Chcete-li odeslat nedelarovanou chybu SOAP, vyvolejte System.ServiceModel.FaultException objekt (tj. ne obecný typ FaultException<TDetail>) a předejte řetězec konstruktoru. Toto je vystaveno klientským aplikacím WCF jako vyvolána System.ServiceModel.FaultException výjimka, kdy je řetězec k dispozici voláním FaultException<TDetail>.ToString metody.

Poznámka:

Pokud deklarujete chybu PROTOKOLU SOAP typu řetězec a pak tuto chybu vyvoláte ve vaší službě jako FaultException<TDetail> místo, kde je System.String parametr typu řetězcová hodnota přiřazena k FaultException<TDetail>.Detail vlastnosti a není k dispozici z FaultException<TDetail>.ToString.

Zpracování chyb

V klientech WCF se jako spravované výjimky generují chyby PROTOKOLU SOAP, ke kterým dochází během komunikace, které jsou zajímavé pro klientské aplikace. I když při provádění libovolného programu může dojít k mnoha výjimkám, aplikace používající programovací model klienta WCF mohou očekávat zpracování výjimek následujících dvou typů v důsledku komunikace.

TimeoutException objekty jsou vyvolány, když operace překročí zadanou dobu časového limitu.

CommunicationException objekty jsou vyvolány v případě, že je v službě nebo klientovi nějaký obnovitelný stav chyby komunikace.

Třída CommunicationException má dva důležité odvozené typy FaultException a obecný FaultException<TDetail> typ.

FaultException Výjimky jsou vyvolány, když naslouchací proces obdrží chybu, která není očekávaná nebo zadaná v kontraktu operace; k tomu obvykle dochází, když je aplikace laděna a služba má ServiceDebugBehavior.IncludeExceptionDetailInFaults vlastnost nastavena na true.

FaultException<TDetail> Výjimky jsou vyvolány v klientovi, pokud je v reakci na obousměrnou operaci přijata chyba zadaná v kontraktu operace (to znamená metoda s atributem OperationContractAttribute nastaveným IsOneWay na false).

Poznámka:

Pokud má služba ServiceBehaviorAttribute.IncludeExceptionDetailInFaults WCF vlastnost nebo ServiceDebugBehavior.IncludeExceptionDetailInFaults vlastnost nastavena na true klient prostředí toto jako nedelarovaný FaultException<TDetail> typ ExceptionDetail. Klienti mohou buď zachytit tuto konkrétní chybu, nebo zpracovat chybu v bloku catch pro FaultException.

Klienti a služby jsou obvykle zajímavé pouze FaultException<TDetail>TimeoutException, a CommunicationException výjimky.

Poznámka:

K dalším výjimkám samozřejmě dochází. Mezi neočekávané výjimky patří závažné selhání, jako jsou System.OutOfMemoryExceptionnapříklad – aplikace by tyto metody neměly zachytávat.

Zachycení výjimek chyb ve správném pořadí

Vzhledem k tomuFaultException<TDetail>, že je odvozen od a FaultException odvozen od FaultExceptionCommunicationException, je důležité zachytit tyto výjimky ve správném pořadí. Pokud například máte blok try/catch, ve kterém jste poprvé zachytávali CommunicationException, všechny zadané a nespecifikované chyby SOAP se tam zpracovávají. Všechny následné bloky catch pro zpracování vlastní FaultException<TDetail> výjimky se nikdy nevyvolají.

Mějte na paměti, že jedna operace může vrátit libovolný počet zadaných chyb. Každá chyba je jedinečný typ a musí být zpracována samostatně.

Zpracování výjimek při zavírání kanálu

Většina předchozí diskuze se týká chyb odeslaných v průběhu zpracování zpráv aplikace, tj. zpráv explicitně odesílaných klientem, když klient volá operace s objektem klienta WCF.

I v případě, že místní objekty disponují objekt, mohou vyvolat nebo maskovat výjimky, ke kterým dochází během procesu recyklace. Něco podobného může nastat, když používáte klientské objekty WCF. Při volání operací posíláte zprávy přes navázané připojení. Zavření kanálu může vyvolat výjimky, pokud připojení nelze vyčistit nebo je již uzavřeno, a to i v případě, že se všechny operace vrátily správně.

Kanály klientských objektů se obvykle zavírají jedním z následujících způsobů:

Ve všech případech zavření kanálu dává kanálu pokyn, aby začal zavírat všechny podkladové kanály, které můžou odesílat zprávy, aby podporoval složité funkce na úrovni aplikace. Pokud například kontrakt vyžaduje relace, pokusí se vytvořit relaci výměnou zpráv s kanálem služby, dokud se relace nenaváže. Když je kanál zavřený, kanál základní relace oznámí službě, že je relace ukončena. V takovém případě, pokud kanál již přerušil, zavřel nebo je jinak nepoužitelný (například při odpojení síťového kabelu), klientský kanál nemůže informovat kanál služby, že relace je ukončena a může dojít k výjimce.

V případě potřeby kanál přerušte.

Protože zavření kanálu může také vyvolat výjimky, doporučuje se, aby kromě zachycení výjimek chyb ve správném pořadí bylo důležité kanál, který byl použit při volání v bloku catch.

Pokud chyba sděluje informace o chybě specifické pro operaci a je možné, že ji ostatní můžou používat, není nutné kanál přerušit (i když tyto případy jsou vzácné). Ve všech ostatních případech doporučujeme kanál přerušit. Ukázku, která demonstruje všechny tyto body, najdete v tématu Očekávané výjimky.

Následující příklad kódu ukazuje, jak zpracovat výjimky chyb SOAP v základní klientské aplikaci, včetně deklarované chyby a nedelarované chyby.

Poznámka:

Tento vzorový kód nepoužívá using konstruktor. Vzhledem k tomu, že uzavírací kanály můžou vyvolat výjimky, doporučuje se nejprve vytvořit klienta WCF a pak otevřít, použít a zavřít klienta WCF ve stejném bloku try. Podrobnosti najdete v tématu Přehled klienta WCF a použití příkazu Zavřít a přerušit k vydání prostředků klienta 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

Viz také