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 voor meer informatie Fouten definiëren en opgeven.) 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 waarin 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 om FaultContractAttribute 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, haalt u de juiste foutvoorwaarde op en genereert u een nieuw System.ServiceModel.FaultException<TDetail> type GreetingFault
met een nieuw GreetingFault
object als het argument, zoals in het volgende codevoorbeeld. Als de client een WCF-clienttoepassing is, wordt deze gebruikt als een beheerde uitzondering waarbij het type van het type GreetingFault
isSystem.ServiceModel.FaultException<TDetail>.
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-declaratiefouten 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 waar, ondervinden clients dergelijke fouten als FaultException<TDetail> uitzonderingen van het type ExceptionDetail.
Belangrijk
Omdat beheerde uitzonderingen interne toepassingsinformatie kunnen blootstellen, kunnen instellingen ServiceBehaviorAttribute.IncludeExceptionDetailInFaults of ServiceDebugBehavior.IncludeExceptionDetailInFaults wcF-clients true
toestaan om informatie te verkrijgen over uitzonderingen voor interne servicebewerkingen, waaronder persoonlijk identificeerbare of andere gevoelige informatie.
Daarom wordt het instellen of true
ServiceDebugBehavior.IncludeExceptionDetailInFaults instellen ServiceBehaviorAttribute.IncludeExceptionDetailInFaults 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, het contract voor het FaultException<TDetail> type ExceptionDetailniet. 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 blootgesteld aan de WCF-clienttoepassingen als een gegenereerde System.ServiceModel.FaultException uitzondering waarbij de tekenreeks beschikbaar is door de methode aan te FaultException<TDetail>.ToString roepen.
Notitie
Als u een SOAP-fout van het type tekenreeks declareert en deze vervolgens in uw service genereert als een FaultException<TDetail> locatie waar de typeparameter een System.String tekenreekswaarde is toegewezen aan de FaultException<TDetail>.Detail eigenschap en niet beschikbaar is van 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 gegenereerd 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 gegenereerd wanneer een fout die is opgegeven in het bewerkingscontract wordt ontvangen als reactie op een tweerichtingsbewerking (dat wil zeggen een methode met een OperationContractAttribute kenmerk dat is IsOneWay ingesteld op false
).
Notitie
Wanneer voor een WCF-service de ServiceBehaviorAttribute.IncludeExceptionDetailInFaults of ServiceDebugBehavior.IncludeExceptionDetailInFaults eigenschap is ingesteld op true
de client, wordt dit aangegeven als een niet-declaratie FaultException<TDetail> van het type ExceptionDetail. Clients kunnen deze specifieke fout ondervangen of de fout afhandelen in een catch-blok voor FaultException.
Normaal gesproken zijn alleen FaultException<TDetail>, TimeoutExceptionen CommunicationException uitzonderingen van belang voor clients en services.
Notitie
Andere uitzonderingen komen natuurlijk wel voor. Onverwachte uitzonderingen zijn catastrofale fouten, zoals System.OutOfMemoryException; toepassingen moeten dergelijke methoden meestal niet vangen.
Foutonderzondering in de juiste volgorde
Omdat FaultException<TDetail> het is afgeleid van FaultExceptionen FaultException is afgeleid van CommunicationException, is het belangrijk om deze uitzonderingen in de juiste volgorde te ondervangen. 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 verwerken 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 vangen van fout-uitzonderingen in de juiste volgorde, het is belangrijk om het kanaal af te breken dat is gebruikt bij het maken van de aanroep in het catch-blok.
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.
Notitie
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