Delen via


Fouten verzenden en ontvangen

SOAP-fouten geven informatie over foutconditie over van een service naar een client en in het dubbelzijdige geval van een client naar een service op een interoperabele manier. Normaal gesproken definieert een service aangepaste foutinhoud en geeft aan welke bewerkingen deze kunnen retourneren. (Zie Fouten definiëren en opgeven voor meer informatie.) In dit onderwerp wordt beschreven hoe een service- of duplexclient deze fouten kan verzenden wanneer de bijbehorende foutvoorwaarde is opgetreden en hoe een client- of servicetoepassing deze fouten afhandelt. Zie Fouten opgeven en afhandelen in contracten en services voor een overzicht van foutafhandeling in WCF-toepassingen (Windows Communication Foundation).

SOAP-fouten verzenden

Gedeclareerde SOAP-fouten zijn fouten waarbij een bewerking een System.ServiceModel.FaultContractAttribute aangepast SOAP-fouttype heeft. Niet-declaratieve SOAP-fouten zijn fouten die niet zijn opgegeven in het contract voor een bewerking.

Gedeclareerde fouten verzenden

Als u een gedeclareerde SOAP-fout wilt verzenden, detecteert u de foutvoorwaarde waarvoor de SOAP-fout geschikt is en genereert u een nieuw System.ServiceModel.FaultException<TDetail> object waarbij de typeparameter een nieuw object is van het type dat is opgegeven in de FaultContractAttribute voor die bewerking. In het volgende codevoorbeeld ziet u het gebruik van FaultContractAttribute om op te geven dat de SampleMethod-bewerking een SOAP-fout kan retourneren met het detailtype 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

Als u de GreetingFault foutinformatie aan de client wilt overbrengen, vangt u de juiste foutvoorwaarde af en gooit u een nieuw System.ServiceModel.FaultException<TDetail> van het type GreetingFault met als argument een nieuw GreetingFault object, zoals in het volgende codevoorbeeld. Als de client een WCF-clienttoepassing is, ervaart deze een beheerde uitzondering waarbij het type System.ServiceModel.FaultException<TDetail> van het type GreetingFault is.

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

Niet-aangegeven fouten verzenden

Het verzenden van niet-declaratieve fouten kan zeer nuttig zijn om snel problemen in WCF-toepassingen vast te stellen en op te sporen, maar het nut ervan als een foutopsporingsprogramma is beperkt. Over het algemeen wordt het aanbevolen om bij het opsporen van fouten de ServiceDebugBehavior.IncludeExceptionDetailInFaults eigenschap te gebruiken. Wanneer u deze waarde instelt op true, ervaren cliënten dergelijke fouten als FaultException<TDetail> uitzonderingen van het type ExceptionDetail.

Belangrijk

Omdat beheerde uitzonderingen interne toepassingsinformatie kunnen blootgeven, kan het instellen van ServiceBehaviorAttribute.IncludeExceptionDetailInFaults of ServiceDebugBehavior.IncludeExceptionDetailInFaults naar true WCF-clients toestaan om informatie te verkrijgen over uitzonderingen van interne servicebewerkingen, waaronder persoonlijk identificeerbare of andere gevoelige informatie.

Daarom wordt het instellen van ServiceBehaviorAttribute.IncludeExceptionDetailInFaults of ServiceDebugBehavior.IncludeExceptionDetailInFaults op true alleen aanbevolen als een manier om tijdelijk fouten in een servicetoepassing op te sporen. Daarnaast bevat de WSDL voor een methode die op deze manier niet-verwerkte beheerde uitzonderingen retourneert, niet het contract voor het FaultException<TDetail> van type ExceptionDetail. Clients moeten de mogelijkheid verwachten van een onbekende SOAP-fout (geretourneerd naar WCF-clients als System.ServiceModel.FaultException objecten) om de foutopsporingsgegevens correct te verkrijgen.

Als u een niet-declaratieve SOAP-fout wilt verzenden, gooit u een System.ServiceModel.FaultException object (dus niet het algemene type FaultException<TDetail>) en geeft u de tekenreeks door aan de constructor. Dit wordt aan de WCF-clienttoepassingen blootgesteld als een gegenereerde System.ServiceModel.FaultException uitzondering waarbij de tekenreeks beschikbaar is door de FaultException<TDetail>.ToString methode aan te roepen.

Opmerking

Als u een SOAP-fout van het type tekenreeks declareert en deze vervolgens als een FaultException<TDetail> in uw service opwerpt, waarbij de typeparameter een System.String is, wordt de tekenreekswaarde toegewezen aan de FaultException<TDetail>.Detail-eigenschap en is deze niet beschikbaar uit FaultException<TDetail>.ToString.

Fouten afhandelen

In WCF-clients worden SOAP-fouten die optreden tijdens communicatie die van belang zijn voor clienttoepassingen gegenereerd als beheerde uitzonderingen. Hoewel er veel uitzonderingen kunnen optreden tijdens het uitvoeren van een programma, kunnen toepassingen die gebruikmaken van het WCF-clientprogrammeringsmodel, uitzonderingen van de volgende twee typen verwerken als gevolg van communicatie.

TimeoutException objecten worden gegenereerd wanneer een bewerking de opgegeven time-outperiode overschrijdt.

CommunicationException objecten worden gegooid wanneer er sprake is van een herstelbare communicatiefout op de service of de client.

De CommunicationException klasse heeft twee belangrijke afgeleide typen en FaultException het algemene FaultException<TDetail> type.

FaultException uitzonderingen worden gegenereerd wanneer een listener een fout ontvangt die niet wordt verwacht of opgegeven in het bewerkingscontract; dit gebeurt meestal wanneer er fouten in de toepassing worden opgespoord en de service de ServiceDebugBehavior.IncludeExceptionDetailInFaults eigenschap heeft ingesteld op true.

FaultException<TDetail> uitzonderingen worden op de client geworpen wanneer een fout die is opgegeven in het bewerkingscontract wordt ontvangen als reactie op een tweerichtings- of bidirectionele bewerking (dat wil zeggen een methode met een OperationContractAttribute kenmerk waarbij IsOneWay is ingesteld op false).

Opmerking

Wanneer voor een WCF-service de ServiceBehaviorAttribute.IncludeExceptionDetailInFaults of ServiceDebugBehavior.IncludeExceptionDetailInFaults eigenschap is ingesteld op true, ervaart de client dit als een niet-gedecleareerde FaultException<TDetail> van het type ExceptionDetail. Klanten kunnen deze specifieke fout opvangen of deze fout afhandelen in een catch-blok voor FaultException.

Normaal gesproken zijn alleen FaultException<TDetail>, TimeoutExceptionen CommunicationException uitzonderingen van belang voor clients en services.

Opmerking

Andere uitzonderingen komen natuurlijk wel voor. Onverwachte uitzonderingen zijn catastrofale fouten, zoals System.OutOfMemoryException; toepassingen moeten dergelijke methoden meestal niet vangen.

Opvangen van foutuitzonderingen in de juiste volgorde

Omdat FaultException<TDetail> is afgeleid van FaultException en FaultException is afgeleid van CommunicationException, is het belangrijk om deze uitzonderingen in de juiste volgorde op te vangen. Als u bijvoorbeeld een try/catch-blok hebt waarin u eerst catcht CommunicationException, worden alle opgegeven en niet-opgegeven SOAP-fouten daar verwerkt. Eventuele volgende catch-blokken voor het afhandelen van een aangepaste FaultException<TDetail> uitzondering worden nooit aangeroepen.

Houd er rekening mee dat één bewerking een willekeurig aantal opgegeven fouten kan retourneren. Elke fout is een uniek type en moet afzonderlijk worden afgehandeld.

Uitzonderingen behandelen bij het sluiten van het kanaal

De meeste van de voorgaande discussies hebben te maken met fouten die zijn verzonden tijdens het verwerken van toepassingsberichten, dat wil gezegd berichten die expliciet door de client worden verzonden wanneer de clienttoepassing bewerkingen aanroept op het WCF-clientobject.

Zelfs bij het verwijderen van lokale objecten kan het object uitzonderingen veroorzaken of maskeren die optreden tijdens het recyclingproces. Er kan iets soortgelijks gebeuren wanneer u WCF-clientobjecten gebruikt. Wanneer u bewerkingen aanroept, verzendt u berichten via een tot stand gebrachte verbinding. Als u het kanaal sluit, kunnen uitzonderingen optreden als de verbinding niet schoon kan worden gesloten of al is gesloten, zelfs als alle bewerkingen correct zijn geretourneerd.

Normaal gesproken worden clientobjectkanalen op een van de volgende manieren gesloten:

  • Wanneer het WCF-clientobject wordt gerecycled.

  • Wanneer de clienttoepassing aanroept ClientBase<TChannel>.Close.

  • Wanneer de clienttoepassing aanroept ICommunicationObject.Close.

  • Wanneer de clienttoepassing een bewerking aanroept die een afsluitbewerking voor een sessie is.

In alle gevallen geeft het sluiten van het kanaal de opdracht om te beginnen met het sluiten van onderliggende kanalen die mogelijk berichten verzenden ter ondersteuning van complexe functionaliteit op toepassingsniveau. Wanneer een contract bijvoorbeeld sessies vereist, probeert een binding een sessie tot stand te brengen door berichten uit te wisselen met het servicekanaal totdat een sessie tot stand is gebracht. Wanneer het kanaal is gesloten, meldt het onderliggende sessiekanaal de service dat de sessie wordt beëindigd. In dit geval, als het kanaal al is afgebroken, gesloten of anderszins onbruikbaar is (bijvoorbeeld wanneer een netwerkkabel niet is aangesloten), kan het clientkanaal het servicekanaal niet informeren dat de sessie wordt beëindigd en kan een uitzondering het gevolg zijn.

Het kanaal indien nodig afbreken

Omdat het sluiten van het kanaal ook uitzonderingen kan genereren, is het raadzaam om naast het opvangen van fout-uitzonderingen in de juiste volgorde het kanaal af te breken dat bij het uitvoeren van de aanroep in het catch-blok is gebruikt.

Als de fout informatie over fouten overbrengt die specifiek is voor een bewerking en het mogelijk blijft dat anderen deze kunnen gebruiken, is het niet nodig om het kanaal af te breken (hoewel deze gevallen zeldzaam zijn). In alle andere gevallen wordt u aangeraden het kanaal af te breken. Zie Verwachte uitzonderingen voor een voorbeeld dat al deze punten laat zien.

In het volgende codevoorbeeld ziet u hoe u SOAP-foutuitzondering kunt verwerken in een eenvoudige clienttoepassing, met inbegrip van een gedeclareerde fout en een niet-declaratieve fout.

Opmerking

Deze voorbeeldcode maakt geen gebruik van de using constructie. Omdat sluitkanalen uitzonderingen kunnen genereren, wordt aanbevolen dat toepassingen eerst een WCF-client maken en vervolgens de WCF-client openen, gebruiken en sluiten in hetzelfde try-blok. Zie voor meer informatie het WCF-clientoverzicht en gebruik Sluiten en afbreken om WCF-clientbronnen vrij te geven.

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

Zie ook