Delen via


Afhandeling van uitzonderingen en fouten

Uitzonderingen worden gebruikt om fouten lokaal te communiceren binnen de service of de client-implementatie. Fouten worden daarentegen gebruikt om fouten over servicegrenzen te communiceren, zoals van de server naar de client of omgekeerd. Naast fouten gebruiken transportkanalen vaak transportspecifieke mechanismen om fouten op transportniveau te communiceren. HTTP-transport gebruikt bijvoorbeeld statuscodes zoals 404 om een niet-bestaande eindpunt-URL te communiceren (er is geen eindpunt om een fout te verzenden). Dit document bestaat uit drie secties die richtlijnen bieden voor aangepaste kanaalauteurs. De eerste sectie bevat richtlijnen voor het definiëren en genereren van uitzonderingen. De tweede sectie bevat richtlijnen voor het genereren en gebruiken van fouten. In de derde sectie wordt uitgelegd hoe u traceringsgegevens kunt opgeven om de gebruiker van uw aangepaste kanaal te helpen bij het oplossen van problemen met actieve toepassingen.

Uitzonderingen

Er zijn twee dingen waarmee u rekening moet houden bij het genereren van een uitzondering: het moet eerst van een type zijn waarmee gebruikers de juiste code kunnen schrijven die op de juiste manier op de uitzondering kan reageren. Ten tweede moet de gebruiker voldoende informatie verstrekken om te begrijpen wat er fout is gegaan, wat de impact op de fout is en hoe deze kan worden opgelost. De volgende secties geven richtlijnen voor uitzonderingstypen en berichten voor WCF-kanalen (Windows Communication Foundation). Er zijn ook algemene richtlijnen voor uitzonderingen in .NET in het document Ontwerprichtlijnen voor uitzonderingen.

Uitzonderingstypen

Alle uitzonderingen die door kanalen worden gegenereerd, moeten een System.TimeoutException, System.ServiceModel.CommunicationExceptionof een type zijn dat is afgeleid van CommunicationException. (Uitzonderingen zoals ObjectDisposedException kunnen ook worden gegenereerd, maar alleen om aan te geven dat de aanroepende code het kanaal heeft misbruikt. Als een kanaal correct wordt gebruikt, mag het alleen de opgegeven uitzonderingen genereren.) WCF biedt zeven uitzonderingstypen die zijn afgeleid van CommunicationException en zijn ontworpen voor gebruik door kanalen. Er zijn andere CommunicationException- afgeleide uitzonderingen die zijn ontworpen om te worden gebruikt door andere onderdelen van het systeem. Deze uitzonderingstypen zijn:

Type uitzondering Betekenis Interne uitzonderingsinhoud Herstelstrategie
AddressAlreadyInUseException Het eindpuntadres dat is opgegeven voor luisteren, wordt al gebruikt. Indien aanwezig, geeft u meer informatie over de transportfout die deze uitzondering heeft veroorzaakt. 2: Huidige gebeurtenis: het huidige product wordt verzonden. PipeException, of HttpListenerExceptionSocketException. Probeer een ander adres.
AddressAccessDeniedException Het proces heeft geen toegang tot het eindpuntadres dat is opgegeven voor luisteren. Indien aanwezig, geeft u meer informatie over de transportfout die deze uitzondering heeft veroorzaakt. Bijvoorbeeld PipeException of HttpListenerException. Probeer het met verschillende referenties.
CommunicationObjectFaultedException Het ICommunicationObject gebruik heeft de status Fout (zie Statuswijzigingen begrijpen) voor meer informatie. Houd er rekening mee dat wanneer een object met meerdere aanroepen die in behandeling zijn, overgaat naar de status Mislukt, slechts één aanroep een uitzondering genereert die betrekking heeft op de fout en de rest van de aanroepen een CommunicationObjectFaultedException. Deze uitzondering wordt meestal gegenereerd omdat een toepassing een uitzondering over het hoofd ziet en probeert een al defect object te gebruiken, mogelijk op een andere thread dan de thread die de oorspronkelijke uitzondering heeft onderschept. Als deze aanwezig is, vindt u informatie over de interne uitzondering. Een nieuw object maken, Afhankelijk van wat de oorzaak is van de ICommunicationObject fout in de eerste plaats, is er mogelijk ander werk vereist om te herstellen.
CommunicationObjectAbortedException De ICommunicationObject gebruikte status is afgebroken (zie Statuswijzigingen begrijpen) voor meer informatie. Net als CommunicationObjectFaultedExceptionbij , geeft deze uitzondering aan dat de toepassing het object heeft aangeroepen Abort , mogelijk vanuit een andere thread, en dat het object om die reden niet meer bruikbaar is. Als deze aanwezig is, vindt u informatie over de interne uitzondering. Een nieuw object maken, Houd er rekening mee dat, afhankelijk van wat de oorzaak is van het ICommunicationObject afbreken van de eerste plaats, er mogelijk andere werkzaamheden nodig zijn om te herstellen.
EndpointNotFoundException Het externe doeleindpunt luistert niet. Dit kan het gevolg zijn van een deel van het eindpuntadres dat onjuist, onherstelbaar of het eindpunt niet beschikbaar is. Voorbeelden hiervan zijn DNS-fout, Queue Manager niet beschikbaar en de service wordt niet uitgevoerd. De interne uitzondering bevat details, meestal van het onderliggende transport. Probeer een ander adres. De afzender kan ook even wachten en het opnieuw proberen als de service niet beschikbaar was
ProtocolException De communicatieprotocollen, zoals beschreven in het beleid van het eindpunt, komen niet overeen tussen eindpunten. Het inhoudstype voor lijsten komt bijvoorbeeld niet overeen of de maximale berichtgrootte is overschreden. Als dit aanwezig is, vindt u meer informatie over de specifieke protocolfout. Is bijvoorbeeld QuotaExceededException de interne uitzondering wanneer de foutoorzaak maxReceivedMessageSize overschrijdt. Herstel: zorg ervoor dat de instellingen voor afzender en ontvangen protocol overeenkomen. Een manier om dit te doen, is door de metagegevens (beleid) van het service-eindpunt opnieuw te importeren en de gegenereerde binding te gebruiken om het kanaal opnieuw te maken.
ServerTooBusyException Het externe eindpunt luistert, maar is niet voorbereid om berichten te verwerken. Indien aanwezig, biedt de interne uitzondering de foutdetails van soap- of transportniveau. Herstel: wacht en voer de bewerking later opnieuw uit.
TimeoutException De bewerking kan niet worden voltooid binnen de time-outperiode. Kan details geven over de time-out. Wacht en voer de bewerking later opnieuw uit.

Definieer alleen een nieuw uitzonderingstype als dat type overeenkomt met een specifieke herstelstrategie die verschilt van alle bestaande uitzonderingstypen. Als u een nieuw uitzonderingstype definieert, moet het zijn afgeleid van CommunicationException of een van de afgeleide klassen.

Uitzonderingsberichten

Uitzonderingsberichten zijn gericht op de gebruiker niet op het programma, zodat ze voldoende informatie moeten verstrekken om de gebruiker te helpen het probleem te begrijpen en op te lossen. De drie essentiële onderdelen van een goed uitzonderingsbericht zijn:

Wat er is gebeurd. Geef een duidelijke beschrijving van het probleem met behulp van termen die betrekking hebben op de gebruikerservaring. Een ongeldig uitzonderingsbericht is bijvoorbeeld 'Ongeldige configuratiesectie'. Hierdoor vraagt de gebruiker zich af welke configuratiesectie onjuist is en waarom deze onjuist is. Een verbeterd bericht is 'Ongeldige configuratiesectie <customBinding>'. Een nog beter bericht is : 'Kan het transport met de naam myTransport niet toevoegen aan de binding met de naam myBinding, omdat de binding al een transport heeft met de naam myTransport'. Dit is een zeer specifiek bericht met behulp van termen en namen die de gebruiker gemakkelijk kan identificeren in het configuratiebestand van de toepassing. Er ontbreken echter nog enkele belangrijke onderdelen.

De significantie van de fout. Tenzij het bericht duidelijk aangeeft wat de fout betekent, vraagt de gebruiker zich waarschijnlijk af of het een fatale fout is of dat deze kan worden genegeerd. In het algemeen moeten berichten leiden met de betekenis of significantie van de fout. Ter verbetering van het vorige voorbeeld kan het bericht 'ServiceHost is niet geopend vanwege een configuratiefout: kan het transport met de naam myTransport niet toevoegen aan de binding myBinding omdat de binding al een transport met de naam myTransport heeft'.

Hoe de gebruiker het probleem moet oplossen. Het belangrijkste onderdeel van het bericht is om de gebruiker te helpen het probleem op te lossen. Het bericht moet enkele richtlijnen of hints bevatten over wat u moet controleren of oplossen om het probleem op te lossen. ServiceHost kan bijvoorbeeld niet worden geopend vanwege een configuratiefout: kan het transport met de naam myTransport niet toevoegen aan de binding met de naam myBinding omdat de binding al een transport met de naam myTransport heeft. Zorg ervoor dat er slechts één transport in de binding is".

Communicerende fouten

SOAP 1.1 en SOAP 1.2 definiëren beide een specifieke structuur voor fouten. Er zijn enkele verschillen tussen de twee specificaties, maar in het algemeen worden de typen Bericht en MessageFault gebruikt om fouten te maken en te verbruiken.

SOAP 1.2 Fault and SOAP 1.1 Fault
SOAP 1.2 Fout (links) en SOAP 1.1 Fout (rechts). In SOAP 1.1 is alleen het foutelement gekwalificeerd als naamruimte.

SOAP definieert een foutbericht als een bericht dat alleen een foutelement bevat (een element waarvan de naam is <env:Fault>) als onderliggend element van <env:Body>. De inhoud van het foutelement verschilt enigszins tussen SOAP 1.1 en SOAP 1.2, zoals weergegeven in afbeelding 1. De System.ServiceModel.Channels.MessageFault klasse normaliseert deze verschillen echter in één objectmodel:

public abstract class MessageFault  
{  
    protected MessageFault();  
  
    public virtual string Actor { get; }  
    public virtual string Node { get; }  
    public static string DefaultAction { get; }  
    public abstract FaultCode Code { get; }  
    public abstract bool HasDetail { get; }  
    public abstract FaultReason Reason { get; }  
  
    public T GetDetail<T>();  
    public T GetDetail<T>( XmlObjectSerializer serializer);  
    public System.Xml.XmlDictionaryReader GetReaderAtDetailContents();  
  
    // other methods omitted  
}  

De Code eigenschap komt overeen met de env:Code (of faultCode in SOAP 1.1) en identificeert het type fout. SOAP 1.2 definieert vijf toegestane waarden voor faultCode (bijvoorbeeld afzender en ontvanger) en definieert een Subcode element dat elke subcodewaarde kan bevatten. (Zie de SOAP 1.2-specificatie voor de lijst met toegestane foutcodes en hun betekenis.) SOAP 1.1 heeft een iets ander mechanisme: het definieert vier faultCode waarden (bijvoorbeeld client en server) die kunnen worden uitgebreid door geheel nieuwe waarden te definiëren of door de punt notatie te gebruiken om specifieker faultCodeste maken, bijvoorbeeld Client.Authentication.

Wanneer u MessageFault gebruikt om fouten te programmeren, wordt de FaultCode.Name en FaultCode.Namespace toegewezen aan de naam en naamruimte van soap 1.2 env:Code of soap 1.1 faultCode. De FaultCode.SubCode wordt toegewezen aan env:Subcode SOAP 1.2 en is null voor SOAP 1.1.

Maak nieuwe foutsubcodes (of nieuwe foutcodes als u SOAP 1.1 gebruikt) als het interessant is om programmatisch onderscheid te maken tussen een fout. Dit is vergelijkbaar met het maken van een nieuw uitzonderingstype. Vermijd het gebruik van de punt notatie met SOAP 1.1-foutcodes. (De WS-I Basic Profile ontmoedigt ook het gebruik van de punt-notatie van de foutcode.)

public class FaultCode  
{  
    public FaultCode(string name);  
    public FaultCode(string name, FaultCode subCode);  
    public FaultCode(string name, string ns);  
    public FaultCode(string name, string ns, FaultCode subCode);  
  
    public bool IsPredefinedFault { get; }  
    public bool IsReceiverFault { get; }  
    public bool IsSenderFault { get; }  
    public string Name { get; }  
    public string Namespace { get; }  
    public FaultCode SubCode { get; }  
  
//  methods omitted  
  
}  

De Reason eigenschap komt overeen met de (of faultString in SOAP 1.1) een door mensen env:Reason leesbare beschrijving van de foutvoorwaarde die vergelijkbaar is met het bericht van een uitzondering. De FaultReason klasse (en SOAP env:Reason/faultString) biedt ingebouwde ondersteuning voor het hebben van meerdere vertalingen in het belang van globalisering.

public class FaultReason  
{  
    public FaultReason(FaultReasonText translation);  
    public FaultReason(IEnumerable<FaultReasonText> translations);  
    public FaultReason(string text);  
  
    public SynchronizedReadOnlyCollection<FaultReasonText> Translations
    {
       get;
    }  
  
 }  

De foutdetailinhoud wordt weergegeven op MessageFault met behulp van verschillende methoden, waaronder de GetDetail<T> en GetReaderAtDetailContents(). Het foutdetail is een ondoorzichtig element voor het dragen van extra details over de fout. Dit is handig als er een willekeurig gestructureerd detail is dat u wilt meenemen met de fout.

Fouten genereren

In deze sectie wordt uitgelegd hoe een fout wordt gegenereerd als reactie op een foutvoorwaarde die is gedetecteerd in een kanaal of in een berichteigenschap die door het kanaal is gemaakt. Een typisch voorbeeld is het terugsturen van een fout als reactie op een aanvraagbericht dat ongeldige gegevens bevat.

Bij het genereren van een fout moet het aangepaste kanaal de fout niet rechtstreeks verzenden, maar moet er een uitzondering worden gegenereerd en moet de bovenstaande laag beslissen of deze uitzondering moet worden geconverteerd naar een fout en hoe deze moet worden verzonden. Om deze conversie te helpen, moet het kanaal een FaultConverter implementatie bieden waarmee de uitzondering die door het aangepaste kanaal wordt gegenereerd, kan worden geconverteerd naar de juiste fout. FaultConverter is gedefinieerd als:

public class FaultConverter  
{  
    public static FaultConverter GetDefaultFaultConverter(  
                                   MessageVersion version);  
    protected abstract bool OnTryCreateFaultMessage(  
                                   Exception exception,
                                   out Message message);  
    public bool TryCreateFaultMessage(  
                                   Exception exception,
                                   out Message message);  
}  

Elk kanaal dat aangepaste fouten genereert, moet het implementeren FaultConverter en retourneren van een aanroep naar GetProperty<FaultConverter>. De aangepaste OnTryCreateFaultMessage implementatie moet de uitzondering converteren naar een fout of delegeren naar het binnenste kanaal FaultConverter. Als het kanaal een transport is, moet het de uitzondering of gemachtigde converteren naar de coderingsprogramma's FaultConverter of de standaardwaarde FaultConverter die is opgegeven in WCF. Met de standaardinstelling FaultConverter worden fouten geconverteerd die overeenkomen met foutberichten die zijn opgegeven door WS-Addressing en SOAP. Hier volgt een voorbeeld OnTryCreateFaultMessage van een implementatie.

public override bool OnTryCreateFaultMessage(Exception exception,
                                             out Message message)  
{  
    if (exception is ...)  
    {  
        message = ...;  
        return true;  
    }  
  
#if IMPLEMENTING_TRANSPORT_CHANNEL  
    FaultConverter encoderConverter =
                    this.encoder.GetProperty<FaultConverter>();  
    if ((encoderConverter != null) &&
        (encoderConverter.TryCreateFaultMessage(  
         exception, out message)))  
    {  
        return true;  
    }  
  
    FaultConverter defaultConverter =
                   FaultConverter.GetDefaultFaultConverter(  
                   this.channel.messageVersion);  
    return defaultConverter.TryCreateFaultMessage(  
                   exception,
                   out message);  
#else  
    FaultConverter inner =
                   this.innerChannel.GetProperty<FaultConverter>();  
    if (inner != null)  
    {  
        return inner.TryCreateFaultMessage(exception, out message);  
    }  
    else  
    {  
        message = null;  
        return false;  
    }  
#endif  
}  

Een implicatie van dit patroon is dat uitzonderingen die worden gegenereerd tussen lagen voor foutvoorwaarden die fouten vereisen, voldoende informatie moeten bevatten voor de bijbehorende foutgenerator om de juiste fout te maken. Als auteur van een aangepast kanaal kunt u uitzonderingstypen definiëren die overeenkomen met verschillende foutvoorwaarden als dergelijke uitzonderingen nog niet bestaan. Houd er rekening mee dat uitzonderingen die kanaallagen doorkruisen, de foutvoorwaarde moeten communiceren in plaats van ondoorzichtige foutgegevens.

Foutcategorieën

Over het algemeen zijn er drie categorieën fouten:

  1. Storingen die overal in de hele stapel zich bevinden. Deze fouten kunnen worden aangetroffen op elke laag in de kanaalstack, bijvoorbeeld InvalidCardinalityAddressingException.

  2. Fouten die overal boven een bepaalde laag in de stack kunnen worden aangetroffen, bijvoorbeeld enkele fouten die betrekking hebben op een gestroomde transactie of beveiligingsrollen.

  3. Fouten die zijn gericht op één laag in de stack, bijvoorbeeld fouten zoals WS-RM-reeksnummerfouten.

Categorie 1. Fouten zijn over het algemeen WS-Adressering en SOAP-fouten. De basisklasse FaultConverter van WCF converteert fouten die overeenkomen met foutberichten die zijn opgegeven door WS-Addressing en SOAP, zodat u de conversie van deze uitzonderingen zelf niet hoeft af te handelen.

Categorie 2. Er treden fouten op wanneer een laag een eigenschap toevoegt aan het bericht dat niet volledig berichtinformatie verbruikt die betrekking heeft op die laag. Er kunnen later fouten worden gedetecteerd wanneer een hogere laag de berichteigenschap vraagt om berichtinformatie verder te verwerken. Dergelijke kanalen moeten de GetProperty opgegeven eerder opgegeven implementeren om de hogere laag in staat te stellen de juiste fout terug te sturen. Een voorbeeld hiervan is transactionMessageProperty. Deze eigenschap wordt toegevoegd aan het bericht zonder alle gegevens in de koptekst volledig te valideren (hiervoor kan contact worden opgenomen met de gedistribueerde transactiecoördinator (DTC).

Categorie 3. Fouten worden alleen gegenereerd en verzonden door één laag in de processor. Daarom zijn alle uitzonderingen opgenomen in de laag. Om de consistentie tussen kanalen te verbeteren en onderhoud te vereenvoudigen, moet uw aangepaste kanaal het patroon gebruiken dat eerder is opgegeven om foutberichten te genereren, zelfs voor interne fouten.

Ontvangen fouten interpreteren

Deze sectie bevat richtlijnen voor het genereren van de juiste uitzondering bij het ontvangen van een foutbericht. De beslissingsstructuur voor het verwerken van een bericht op elke laag in de stack is als volgt:

  1. Als de laag van mening is dat het bericht ongeldig is, moet de laag de verwerking van het 'ongeldige bericht' uitvoeren. Dergelijke verwerking is specifiek voor de laag, maar kan het verwijderen van het bericht, het traceren of het genereren van een uitzondering die wordt geconverteerd naar een fout omvatten. Voorbeelden hiervan zijn beveiliging die een bericht ontvangt dat niet goed is beveiligd, of RM ontvangt een bericht met een ongeldig volgnummer.

  2. Als het bericht anders een foutbericht is dat specifiek van toepassing is op de laag en het bericht niet zinvol is buiten de interactie van de laag, moet de laag de foutvoorwaarde afhandelen. Een voorbeeld hiervan is een rm-reeks geweigerde fout die betekenisloos is voor lagen boven het RM-kanaal en dat impliceert dat het RM-kanaal fouten veroorzaakt en wordt veroorzaakt door bewerkingen die in behandeling zijn.

  3. Anders moet het bericht worden geretourneerd vanuit Request() of Receive(). Dit omvat gevallen waarin de laag de fout herkent, maar de fout geeft alleen aan dat een aanvraag is mislukt en niet impliceert dat het kanaal fouten veroorzaakt en wordt veroorzaakt door bewerkingen die in behandeling zijn. Om de bruikbaarheid in een dergelijk geval te verbeteren, moet de laag een FaultConverter afgeleide klasse implementeren GetProperty<FaultConverter> en retourneren die de fout kan converteren naar een uitzondering door deze te overschrijvenOnTryCreateException.

Het volgende objectmodel ondersteunt het converteren van berichten naar uitzonderingen:

public class FaultConverter  
{  
    public static FaultConverter GetDefaultFaultConverter(  
                                  MessageVersion version);  
    protected abstract bool OnTryCreateException(  
                                 Message message,
                                 MessageFault fault,
                                 out Exception exception);  
    public bool TryCreateException(  
                                 Message message,
                                 MessageFault fault,
                                 out Exception exception);  
}  

Een kanaallaag kan worden geïmplementeerd GetProperty<FaultConverter> ter ondersteuning van het converteren van foutberichten naar uitzonderingen. Hiervoor overschrijft OnTryCreateException en inspecteert u het foutbericht. Als dit wordt herkend, voert u de conversie uit, anders vraagt u het binnenste kanaal om het te converteren. Transportkanalen moeten delegeren om de standaard SOAP/WS-Addressing FaultConverter te FaultConverter.GetDefaultFaultConverter krijgen.

Een typische implementatie ziet er als volgt uit:

public override bool OnTryCreateException(  
                            Message message,
                            MessageFault fault,
                            out Exception exception)  
{  
    if (message.Action == "...")  
    {  
        exception = ...;  
        return true;  
    }  
    // OR  
    if ((fault.Code.Name == "...") && (fault.Code.Namespace == "..."))  
    {  
        exception = ...;  
        return true;  
    }  
  
    if (fault.IsMustUnderstand)  
    {  
        if (fault.WasHeaderNotUnderstood(  
                   message.Headers, "...", "..."))  
        {  
            exception = new ProtocolException(...);  
            return true;  
        }  
    }  
  
#if IMPLEMENTING_TRANSPORT_CHANNEL  
    FaultConverter encoderConverter =
              this.encoder.GetProperty<FaultConverter>();  
    if ((encoderConverter != null) &&
        (encoderConverter.TryCreateException(  
                              message, fault, out exception)))  
    {  
        return true;  
    }  
  
    FaultConverter defaultConverter =  
             FaultConverter.GetDefaultFaultConverter(  
                             this.channel.messageVersion);  
    return defaultConverter.TryCreateException(  
                             message, fault, out exception);  
#else  
    FaultConverter inner =
                    this.innerChannel.GetProperty<FaultConverter>();  
    if (inner != null)  
    {  
        return inner.TryCreateException(message, fault, out exception);  
    }  
    else  
    {  
        exception = null;  
        return false;  
    }  
#endif  
}  

Voor specifieke foutvoorwaarden met verschillende herstelscenario's kunt u overwegen om een afgeleide klasse van ProtocolException.

MustUnderstand Processing

SOAP definieert een algemene fout voor het signaleren dat een vereiste header niet door de ontvanger is begrepen. Deze fout wordt de mustUnderstand fout genoemd. In WCF genereren mustUnderstand aangepaste kanalen nooit fouten. In plaats daarvan controleert de WCF-dispatcher, die zich boven aan de WCF-communicatiestack bevindt, of alle headers die zijn gemarkeerd als MustUnderstand=true, door de onderliggende stack zijn begrepen. Als er geen fout is begrepen, wordt er op dat moment een mustUnderstand fout gegenereerd. (De gebruiker kan ervoor kiezen deze mustUnderstand verwerking uit te schakelen en de toepassing alle berichtkoppen te laten ontvangen. In dat geval is de toepassing verantwoordelijk voor het uitvoeren van mustUnderstand verwerking.) De gegenereerde fout bevat een NotUnderstood-header die de namen van alle headers met MustUnderstand=true bevat die niet zijn begrepen.

Als uw protocolkanaal een aangepaste header met MustUnderstand=true verzendt en een mustUnderstand fout ontvangt, moet worden bepaald of deze fout wordt veroorzaakt door de header die wordt verzonden. Er zijn twee leden in de MessageFault klas die nuttig zijn voor dit:

public class MessageFault  
{  
    ...  
    public bool IsMustUnderstandFault { get; }  
    public static bool WasHeaderNotUnderstood(MessageHeaders headers,
        string name, string ns) { }  
    ...  
  
}  

IsMustUnderstandFault retourneert true als de fout een mustUnderstand fout is. WasHeaderNotUnderstood retourneert true als de header met de opgegeven naam en naamruimte is opgenomen in de fout als een NotUnderstood-header. Anders wordt het geretourneerd false.

Als een kanaal een header verzendt die is gemarkeerd als MustUnderstand = true, moet die laag ook het API-patroon voor het genereren van uitzonderingen implementeren en fouten die door die header worden veroorzaakt, converteren mustUnderstand naar een nuttigere uitzondering zoals eerder beschreven.

Tracering

Het .NET Framework biedt een mechanisme om de uitvoering van programma's te traceren als een manier om de diagnose van productietoepassingen of onregelmatige problemen te helpen, waarbij het niet mogelijk is om alleen een foutopsporingsprogramma te koppelen en de code te doorlopen. De kernonderdelen van dit mechanisme bevinden zich in de System.Diagnostics naamruimte en bestaan uit:

Tracing components

Tracering vanuit een aangepast kanaal

Aangepaste kanalen moeten traceringsberichten schrijven om te helpen bij het diagnosticeren van problemen wanneer het niet mogelijk is om een foutopsporingsprogramma toe te voegen aan de actieve toepassing. Dit omvat twee taken op hoog niveau: het instantiëren van een TraceSource en het aanroepen van de methoden voor het schrijven van traceringen.

Wanneer u een TraceSourceinstantie maakt, wordt de tekenreeks die u opgeeft de naam van die bron. Deze naam wordt gebruikt voor het configureren (traceringsniveau inschakelen/uitschakelen/instellen) van de traceringsbron. Deze wordt ook weergegeven in de traceringsuitvoer zelf. Aangepaste kanalen moeten een unieke bronnaam gebruiken om lezers van de traceringsuitvoer te helpen begrijpen waar de traceringsinformatie vandaan komt. Het is gebruikelijk om de naam van de assembly te gebruiken die de informatie schrijft als de naam van de traceringsbron. WCF maakt bijvoorbeeld gebruik van System.ServiceModel als traceringsbron voor informatie die is geschreven uit de System.ServiceModel-assembly.

Zodra u een traceringsbron hebt, roept u de TraceDatabijbehorende of TraceEventTraceInformation methoden aan om traceringsvermeldingen naar de traceerlisteners te schrijven. Voor elke traceringsvermelding die u schrijft, moet u het type gebeurtenis classificeren als een van de gebeurtenistypen die zijn gedefinieerd in TraceEventType. Deze classificatie en de instelling voor traceringsniveau in de configuratie bepalen of de traceringsvermelding uitvoer is voor de listener. Als u bijvoorbeeld het traceringsniveau instelt in de configuratie, Warning kunnen WarningError en Critical traceringsvermeldingen worden geschreven, maar worden informatie en uitgebreide vermeldingen geblokkeerd. Hier volgt een voorbeeld van het instantiëren van een traceringsbron en het schrijven van een vermelding op informatieniveau:

using System.Diagnostics;  
//...  
TraceSource udpSource = new TraceSource("Microsoft.Samples.Udp");  
//...  
udpsource.TraceInformation("UdpInputChannel received a message");  

Belangrijk

Het wordt ten zeerste aanbevolen om een traceringsbronnaam op te geven die uniek is voor uw aangepaste kanaal om uitvoerlezers te helpen begrijpen waar de uitvoer vandaan komt.

Integreren met traceringsviewer

Traceringen die door uw kanaal worden gegenereerd, kunnen worden uitgevoerd in een indeling die kan worden gelezen door het hulpprogramma Service Trace Viewer (SvcTraceViewer.exe) met behulp van System.Diagnostics.XmlWriterTraceListener als traceringslistener. Dit is niet iets wat u, als kanaalontwikkelaar, moet doen. In plaats daarvan is het de toepassingsgebruiker (of de persoon die problemen met de toepassing opspoort) die deze traceerlister moet configureren in het configuratiebestand van de toepassing. De volgende configuratie voert bijvoorbeeld traceringsgegevens uit van zowel System.ServiceModel als Microsoft.Samples.Udp naar het bestand met de naam TraceEventsFile.e2e:

<configuration>  
  <system.diagnostics>  
    <sources>  
      <!-- configure System.ServiceModel trace source -->  
      <source name="System.ServiceModel" switchValue="Verbose"
              propagateActivity="true">  
        <listeners>  
          <add name="e2e" />  
        </listeners>  
      </source>  
      <!-- configure Microsoft.Samples.Udp trace source -->  
      <source name="Microsoft.Samples.Udp" switchValue="Verbose" >  
        <listeners>  
          <add name="e2e" />  
        </listeners>  
      </source>  
    </sources>  
    <!--   
    Define a shared trace listener that outputs to TraceFile.e2e  
    The listener name is e2e   
    -->  
    <sharedListeners>  
      <add name="e2e" type="System.Diagnostics.XmlWriterTraceListener"  
        initializeData=".\TraceFile.e2e"/>  
    </sharedListeners>  
    <trace autoflush="true" />  
  </system.diagnostics>  
</configuration>  

Gestructureerde gegevens traceren

System.Diagnostics.TraceSource heeft een methode die een TraceData of meer objecten gebruikt die moeten worden opgenomen in de traceringsvermelding. Over het algemeen wordt de Object.ToString methode aangeroepen voor elk object en wordt de resulterende tekenreeks geschreven als onderdeel van de traceringsvermelding. System.Diagnostics.XmlWriterTraceListener Wanneer u traceringen uitvoert, kunt u een System.Xml.XPath.IXPathNavigable als gegevensobject doorgeven aan TraceData. De resulterende traceringsvermelding bevat de XML die door de System.Xml.XPath.XPathNavigator. Hier volgt een voorbeeldvermelding met XML-toepassingsgegevens:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">  
  <System xmlns="...">  
    <EventID>12</EventID>  
    <Type>3</Type>  
    <SubType Name="Information">0</SubType>  
    <Level>8</Level>  
    <TimeCreated SystemTime="2006-01-13T22:58:03.0654832Z" />  
    <Source Name="Microsoft.ServiceModel.Samples.Udp" />  
    <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />  
    <Execution  ProcessName="UdpTestConsole"
                ProcessID="3348" ThreadID="4" />  
    <Channel />  
    <Computer>COMPUTER-LT01</Computer>  
  </System>  
<!-- XML application data -->  
  <ApplicationData>  
  <TraceData>  
   <DataItem>  
   <TraceRecord
     Severity="Information"  
     xmlns="…">  
        <TraceIdentifier>some trace id</TraceIdentifier>  
        <Description>EndReceive called</Description>  
        <AppDomain>UdpTestConsole.exe</AppDomain>  
        <Source>UdpInputChannel</Source>  
      </TraceRecord>  
    </DataItem>  
  </TraceData>  
  </ApplicationData>  
</E2ETraceEvent>  

De WCF-traceringsviewer begrijpt het schema van het TraceRecord eerder weergegeven element en extraheert de gegevens uit de onderliggende elementen en geeft deze weer in tabelvorm. Uw kanaal moet dit schema gebruiken bij het traceren van gestructureerde toepassingsgegevens om gebruikers te helpen de gegevens te lezen Svctraceviewer.exe.