Delen via


De berichtklasse gebruiken

De Message klasse is fundamenteel voor Windows Communication Foundation (WCF). Alle communicatie tussen clients en services resulteert uiteindelijk in Message het verzenden en ontvangen van exemplaren.

Normaal gesproken zou u niet rechtstreeks met de Message klas communiceren. In plaats daarvan worden wcF-servicemodelconstructies, zoals gegevenscontracten, berichtcontracten en bewerkingscontracten, gebruikt om binnenkomende en uitgaande berichten te beschrijven. In sommige geavanceerde scenario's kunt u echter de Message klasse rechtstreeks programmeren. U kunt bijvoorbeeld de Message klasse gebruiken:

  • Wanneer u een alternatieve manier nodig hebt om uitgaande berichtinhoud te maken (bijvoorbeeld het rechtstreeks vanuit een bestand op schijf maken) in plaats van .NET Framework-objecten te serialiseren.

  • Wanneer u een alternatieve manier nodig hebt om de inhoud van binnenkomende berichten te gebruiken (bijvoorbeeld wanneer u een XSLT-transformatie wilt toepassen op de onbewerkte XML-inhoud) in plaats van deserialiseren in .NET Framework-objecten.

  • Wanneer u berichten op een algemene manier moet verwerken, ongeacht de inhoud van berichten (bijvoorbeeld wanneer u berichten routert of doorstuurt bij het bouwen van een router, load balancer of een systeem voor publiceren/abonneren).

Voordat u de Message klasse gebruikt, moet u vertrouwd raken met de WCF-architectuur voor gegevensoverdracht in het architectuuroverzicht van gegevensoverdracht.

A Message is een container voor algemeen gebruik voor gegevens, maar het ontwerp volgt het ontwerp van een bericht in het SOAP-protocol nauw. Net als in SOAP heeft een bericht zowel een berichttekst als kopteksten. De hoofdtekst van het bericht bevat de werkelijke nettoladinggegevens, terwijl de headers extra benoemde gegevenscontainers bevatten. De regels voor het lezen en schrijven van de hoofdtekst en de kopteksten zijn bijvoorbeeld verschillend, de headers worden altijd gebufferd in het geheugen en kunnen in willekeurige volgorde worden geopend, terwijl de hoofdtekst slechts één keer kan worden gelezen en kan worden gestreamd. Normaal gesproken wordt de hoofdtekst van het bericht toegewezen aan de SOAP-hoofdtekst en worden de berichtkoppen toegewezen aan de SOAP-headers.

De berichtklasse gebruiken in bewerkingen

U kunt de Message klasse gebruiken als invoerparameter van een bewerking, de retourwaarde van een bewerking of beide. Als Message er ergens in een bewerking wordt gebruikt, zijn de volgende beperkingen van toepassing:

  • De bewerking kan geen of out ref parameters bevatten.

  • Er mogen niet meer dan één input parameter zijn. Als de parameter aanwezig is, moet dit bericht of een berichtcontracttype zijn.

  • Het retourtype moet ofwel , Messageof een berichtcontracttype zijnvoid.

Het volgende codevoorbeeld bevat een geldig bewerkingscontract.

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    Message GetData();

    [OperationContract]
    void PutData(Message m);
}
<ServiceContract()> _
Public Interface IMyService
    <OperationContract()> _
    Function GetData() As Message

    <OperationContract()> _
    Sub PutData(ByVal m As Message)
End Interface

Basisberichten maken

De Message klasse biedt statische CreateMessage factory-methoden die u kunt gebruiken om basisberichten te maken.

Alle CreateMessage overbelastingen hebben een versieparameter van het type MessageVersion die aangeeft welke SOAP- en WS-Adresseringsversies voor het bericht moeten worden gebruikt. Als u dezelfde protocolversies wilt gebruiken als het binnenkomende bericht, kunt u de IncomingMessageVersion eigenschap gebruiken op het OperationContext exemplaar dat u hebt verkregen uit de Current eigenschap. De meeste CreateMessage overbelastingen hebben ook een tekenreeksparameter die aangeeft dat de SOAP-actie moet worden gebruikt voor het bericht. De versie kan worden ingesteld om soap-envelopgeneratie uit te None schakelen. Het bericht bestaat alleen uit de hoofdtekst.

Berichten van objecten maken

De meest eenvoudige CreateMessage overbelasting die slechts een versie gebruikt en een actie maakt een bericht met een lege hoofdtekst. Een andere overbelasting heeft een extra Object parameter. Hiermee wordt een bericht gemaakt waarvan de hoofdtekst de geserialiseerde weergave van het opgegeven object is. Gebruik de DataContractSerializer standaardinstellingen voor serialisatie. Als u een andere serialisatiefunctie wilt gebruiken of als u de DataContractSerializer geconfigureerde anders wilt configureren, gebruikt u de CreateMessage overbelasting die ook een XmlObjectSerializer parameter gebruikt.

Als u bijvoorbeeld een object in een bericht wilt retourneren, kunt u de volgende code gebruiken.

public class MyService1 : IMyService
{
    public Message GetData()
    {
        Person p = new Person();
        p.name = "John Doe";
        p.age = 42;
        MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
        return Message.CreateMessage(ver, "GetDataResponse", p);
    }

    public void PutData(Message m)
    {
        // Not implemented.
    }
}
[DataContract]
public class Person
{
    [DataMember] public string name;
    [DataMember] public int age;
}
Public Class MyService1
    Implements IMyService

    Public Function GetData() As Message _
     Implements IMyService.GetData
        Dim p As New Person()
        p.name = "John Doe"
        p.age = 42
        Dim ver As MessageVersion = _
          OperationContext.Current.IncomingMessageVersion
        Return Message.CreateMessage(ver, "GetDataResponse", p)

    End Function


    Public Sub PutData(ByVal m As Message) _
    Implements IMyService.PutData
        ' Not implemented.
    End Sub
End Class
<DataContract()> _
Public Class Person
    <DataMember()> _
    Public name As String
    <DataMember()> _
    Public age As Integer
End Class

Berichten maken van XML-lezers

Er zijn CreateMessage overbelastingen die een XmlReader of een XmlDictionaryReader voor de hoofdtekst innemen in plaats van een object. In dit geval bevat de hoofdtekst van het bericht de XML die het resultaat is van het lezen van de doorgegeven XML-lezer. De volgende code retourneert bijvoorbeeld een bericht met de hoofdtekst die is gelezen uit een XML-bestand.

public class MyService2 : IMyService
{
    public Message GetData()
    {
        FileStream stream = new FileStream("myfile.xml",FileMode.Open);
        XmlDictionaryReader xdr =
               XmlDictionaryReader.CreateTextReader(stream,
                           new XmlDictionaryReaderQuotas());
        MessageVersion ver =
            OperationContext.Current.IncomingMessageVersion;
        return Message.CreateMessage(ver,"GetDataResponse",xdr);
    }

    public void PutData(Message m)
    {
        // Not implemented.
    }
}
Public Class MyService2
    Implements IMyService

    Public Function GetData() As Message Implements IMyService.GetData
        Dim stream As New FileStream("myfile.xml", FileMode.Open)
        Dim xdr As XmlDictionaryReader = _
        XmlDictionaryReader.CreateTextReader(stream, New XmlDictionaryReaderQuotas())
        Dim ver As MessageVersion = OperationContext.Current.IncomingMessageVersion
        Return Message.CreateMessage(ver, "GetDataResponse", xdr)

    End Function


    Public Sub PutData(ByVal m As Message) Implements IMyService.PutData

    End Sub
End Class

Daarnaast zijn CreateMessage er overbelastingen die een XmlReader of een XmlDictionaryReader die het hele bericht vertegenwoordigen en niet alleen de hoofdtekst. Deze overbelastingen hebben ook een geheel getalparameter maxSizeOfHeaders . Headers worden altijd in het geheugen gebufferd zodra het bericht is gemaakt en deze parameter beperkt de hoeveelheid buffering die plaatsvindt. Het is belangrijk om deze parameter in te stellen op een veilige waarde als de XML afkomstig is van een niet-vertrouwde bron om de mogelijkheid van een Denial of Service-aanval te beperken. De SOAP- en WS-Adresseringsversies van het bericht die de XML-lezer vertegenwoordigt, moeten overeenkomen met de versies die worden aangegeven met behulp van de versieparameter.

Berichten maken met BodyWriter

Eén CreateMessage overbelasting neemt een BodyWriter exemplaar om de hoofdtekst van het bericht te beschrijven. A BodyWriter is een abstracte klasse die kan worden afgeleid om aan te passen hoe berichtteksten worden gemaakt. U kunt uw eigen BodyWriter afgeleide klasse maken om berichtteksten op een aangepaste manier te beschrijven. U moet de BodyWriter.OnWriteBodyContents methode die een XmlDictionaryWritergebruikt, overschrijven. Deze methode is verantwoordelijk voor het schrijven van de hoofdtekst.

Hoofdtekstschrijvers kunnen worden gebufferd of niet-gebufferd (gestreamd). Schrijvers van gebufferde lichamen kunnen hun inhoud op elk gewenst moment uitschrijven, terwijl gestreamde personen hun inhoud slechts één keer kunnen uitschrijven. De IsBuffered eigenschap geeft aan of een body writer is gebufferd of niet. U kunt dit instellen voor uw hoofdtekstschrijver door de beveiligde BodyWriter constructor aan te roepen die een isBuffered booleaanse parameter gebruikt. Hoofdschrijvers ondersteunen het maken van een gebufferde lichaamschrijver van een niet-gebufferde lichaamschrijver. U kunt de OnCreateBufferedCopy methode overschrijven om dit proces aan te passen. Standaard wordt een in-memory buffer gebruikt die de XML bevat die wordt geretourneerd door OnWriteBodyContents . OnCreateBufferedCopy neemt een maxBufferSize geheel getalparameter. Als u deze methode overschrijft, moet u geen buffers maken die groter zijn dan deze maximale grootte.

De BodyWriter klasse biedt de WriteBodyContents en CreateBufferedCopy methoden, die in wezen dunne wrappers OnWriteBodyContents zijn en OnCreateBufferedCopy methoden, respectievelijk. Met deze methoden wordt statuscontrole uitgevoerd om ervoor te zorgen dat een niet-gebufferde body writer niet meer dan één keer wordt geopend. Deze methoden worden alleen rechtstreeks aangeroepen bij het maken van aangepaste Message afgeleide klassen op BodyWritersbasis van .

Foutberichten maken

U kunt bepaalde CreateMessage overbelastingen gebruiken om SOAP-foutberichten te maken. De meest elementaire hiervan is een MessageFault object dat de fout beschrijft. Andere overbelastingen worden voor het gemak geboden. De eerste dergelijke overbelasting neemt een FaultCode en een redentekenreeks en maakt een MessageFault gebruik van MessageFault.CreateFault deze informatie. De andere overbelasting neemt een detailobject en geeft het ook door aan CreateFault samen met de foutcode en de reden. Met de volgende bewerking wordt bijvoorbeeld een fout geretourneerd.

public class MyService3 : IMyService
{
    public Message GetData()
    {
        FaultCode fc = new FaultCode("Receiver");
        MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
            return Message.CreateMessage(ver,fc,"Bad data","GetDataResponse");
    }

    public void PutData(Message m)
    {
        // Not implemented.
    }
}
Public Class MyService3
    Implements IMyService

    Public Function GetData() As Message Implements IMyService.GetData
        Dim fc As New FaultCode("Receiver")
        Dim ver As MessageVersion = OperationContext.Current.IncomingMessageVersion
        Return Message.CreateMessage(ver, fc, "Bad data", "GetDataResponse")

    End Function


    Public Sub PutData(ByVal m As Message) Implements IMyService.PutData

    End Sub
End Class

Berichttekstgegevens extraheren

De Message klasse ondersteunt meerdere manieren om informatie uit de hoofdtekst te extraheren. Deze kunnen worden geclassificeerd in de volgende categorieën:

  • De volledige berichttekst in één keer naar een XML-schrijver laten schrijven. Dit wordt een bericht geschreven.

  • Een XML-lezer over de hoofdtekst van het bericht halen. Hierdoor hebt u later toegang tot de hoofdtekst van het bericht, indien nodig. Dit wordt een bericht gelezen.

  • Het hele bericht, inclusief de hoofdtekst, kan worden gekopieerd naar een buffer in het geheugen van het MessageBuffer type. Dit wordt het kopiëren van een bericht genoemd.

U hebt slechts eenmaal toegang tot de hoofdtekst Message , ongeacht hoe deze wordt geopend. Een berichtobject heeft een State eigenschap die in eerste instantie is ingesteld op Gemaakt. Met de drie toegangsmethoden die in de voorgaande lijst worden beschreven, wordt de status respectievelijk ingesteld op Geschreven, Gelezen en Gekopieerd. Daarnaast kan een Close methode de status instellen op Gesloten wanneer de hoofdtekst van het bericht niet meer nodig is. De hoofdtekst van het bericht kan alleen worden geopend in de status Gemaakt en er is geen manier om terug te gaan naar de status Gemaakt nadat de status is gewijzigd.

Berichten schrijven

Met WriteBodyContents(XmlDictionaryWriter) de methode wordt de hoofdinhoud van een bepaald Message exemplaar weggeschreven naar een bepaalde XML-schrijver. De WriteBody methode doet hetzelfde, behalve dat deze de hoofdtekstinhoud in het juiste wrapper-element plaatst (bijvoorbeeld <soap:body>). Ten slotte WriteMessage schrijft u het hele bericht uit, inclusief de soap-envelop en de kopteksten. Als SOAP is uitgeschakeld (Version is MessageVersion.None), doen alle drie de methoden hetzelfde: ze schrijven de hoofdtekst van het bericht op.

Met de volgende code wordt bijvoorbeeld de hoofdtekst van een binnenkomend bericht naar een bestand geschreven.

public class MyService4 : IMyService
{
    public void PutData(Message m)
    {
        FileStream stream = new FileStream("myfile.xml",FileMode.Create);
        XmlDictionaryWriter xdw =
            XmlDictionaryWriter.CreateTextWriter(stream);
        m.WriteBodyContents(xdw);
        xdw.Flush();
    }

    public Message GetData()
    {
        throw new NotImplementedException();
    }
}
Public Class MyService4
    Implements IMyService

    Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
        Dim stream As New FileStream("myfile.xml", FileMode.Create)
        Dim xdw As XmlDictionaryWriter = XmlDictionaryWriter.CreateTextWriter(stream)
        m.WriteBodyContents(xdw)
        xdw.Flush()

    End Sub


    Public Function GetData() As Message Implements IMyService.GetData
        Throw New NotImplementedException()

    End Function
End Class

Twee extra helpermethoden schrijven bepaalde SOAP start-elementtags uit. Deze methoden hebben geen toegang tot de berichttekst en dus wijzigen ze de berichtstatus niet. Deze omvatten:

  • WriteStartBody schrijft het hoofdtekstelement van het begin, bijvoorbeeld <soap:Body>.

  • WriteStartEnvelope schrijft bijvoorbeeld het begin-envelopelement <soap:Envelope>.

Als u de bijbehorende tags voor eindelementen wilt schrijven, roept WriteEndElement u de bijbehorende XML-schrijver aan. Deze methoden worden zelden rechtstreeks aangeroepen.

Berichten lezen

De primaire manier om een berichttekst te lezen, is door te bellen GetReaderAtBodyContents. U krijgt een XmlDictionaryReader bericht dat u kunt gebruiken om de hoofdtekst van het bericht te lezen. Houd er rekening mee dat de Message overgangen naar de leesstatus zodra GetReaderAtBodyContents deze worden aangeroepen en niet wanneer u de geretourneerde XML-lezer gebruikt.

Met de GetBody methode kunt u ook toegang krijgen tot de hoofdtekst van het bericht als een getypt object. Intern gebruikt GetReaderAtBodyContentsdeze methode en wordt de berichtstatus dus ook overgemaakt naar de Read status (zie de State eigenschap).

Het is een goede gewoonte om de IsEmpty eigenschap te controleren, in welk geval de hoofdtekst van het bericht leeg is en GetReaderAtBodyContents een InvalidOperationException. Als het een ontvangen bericht is (bijvoorbeeld het antwoord), kunt u ook controleren IsFaultof het bericht een fout bevat.

De meest eenvoudige overbelasting van deserialisatie van de hoofdtekst van GetBody het bericht in een exemplaar van een type (aangegeven door de algemene parameter) met behulp van een DataContractSerializer geconfigureerd met de standaardinstellingen en met het MaxItemsInObjectGraph quotum uitgeschakeld. Als u een andere serialisatie-engine wilt gebruiken of de DataContractSerializer engine op een niet-standaard manier wilt configureren, gebruikt u de GetBody overbelasting die een XmlObjectSerializer.

Met de volgende code worden bijvoorbeeld gegevens geëxtraheerd uit een berichttekst die een geserialiseerd Person object bevat en worden de naam van de persoon afgedrukt.

    public class MyService5 : IMyService
    {
        public void PutData(Message m)
        {
            Person p = m.GetBody<Person>();
            Console.WriteLine(p.name);
        }

        public Message GetData()
        {
            throw new NotImplementedException();
        }
    }
}
namespace Samples2
{
    [ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        Message GetData();

        [OperationContract]
        void PutData(Message m);
    }

    [DataContract]
    public class Person
    {
        [DataMember] public string name;
        [DataMember] public int age;
    }
    Public Class MyService5
        Implements IMyService

        Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
            Dim p As Person = m.GetBody(Of Person)()
            Console.WriteLine(p.name)

        End Sub


        Public Function GetData() As Message Implements IMyService.GetData
            Throw New NotImplementedException()

        End Function
    End Class
End Namespace
Namespace Samples2
    <ServiceContract()> _
    Public Interface IMyService
        <OperationContract()> _
        Function GetData() As Message

        <OperationContract()> _
        Sub PutData(ByVal m As Message)
    End Interface

    <DataContract()> _
    Public Class Person
        <DataMember()> _
        Public name As String
        <DataMember()> _
        Public age As Integer
    End Class

Een bericht naar een buffer kopiëren

Soms is het nodig om meerdere keren toegang te krijgen tot de berichttekst, bijvoorbeeld om hetzelfde bericht door te sturen naar meerdere bestemmingen als onderdeel van een uitgeversabonneesysteem. In dit geval is het noodzakelijk om het hele bericht (inclusief de hoofdtekst) in het geheugen te bufferen. U kunt dit doen door te bellen CreateBufferedCopy(Int32). Deze methode gebruikt een geheel getalparameter die de maximale buffergrootte vertegenwoordigt en maakt een buffer die niet groter is dan deze grootte. Het is belangrijk om dit in te stellen op een veilige waarde als het bericht afkomstig is van een niet-vertrouwde bron.

De buffer wordt geretourneerd als een MessageBuffer exemplaar. U kunt op verschillende manieren toegang krijgen tot gegevens in de buffer. De primaire manier is om CreateMessage exemplaren te maken Message vanuit de buffer.

Een andere manier om toegang te krijgen tot de gegevens in de buffer is door de IXPathNavigable interface te implementeren die door de MessageBuffer klasse wordt geïmplementeerd om rechtstreeks toegang te krijgen tot de onderliggende XML. Met sommige CreateNavigator overbelastingen kunt u navigators maken System.Xml.XPath die worden beveiligd door een knooppuntquotum, waardoor het aantal XML-knooppunten dat kan worden bezocht, wordt beperkt. Dit helpt denial of service-aanvallen te voorkomen op basis van een lange verwerkingstijd. Deze aanhalingsteken is standaard uitgeschakeld. Met sommige CreateNavigator overbelastingen kunt u opgeven hoe witruimte in de XML moet worden verwerkt met behulp van de XmlSpace opsomming, waarbij de standaardwaarde is XmlSpace.None.

Een laatste manier om toegang te krijgen tot de inhoud van een berichtbuffer is door de inhoud ervan naar een stream te schrijven met behulp van WriteMessage.

In het volgende voorbeeld ziet u hoe u met een MessageBuffer: een binnenkomend bericht wordt doorgestuurd naar meerdere geadresseerden en vervolgens bent aangemeld bij een bestand. Zonder buffering is dit niet mogelijk, omdat de hoofdtekst van het bericht vervolgens slechts één keer kan worden geopend.

[ServiceContract]
public class ForwardingService
{
    private List<IOutputChannel> forwardingAddresses;

    [OperationContract]
    public void ForwardMessage (Message m)
    {
        //Copy the message to a buffer.
        MessageBuffer mb = m.CreateBufferedCopy(65536);

        //Forward to multiple recipients.
        foreach (IOutputChannel channel in forwardingAddresses)
        {
            Message copy = mb.CreateMessage();
            channel.Send(copy);
        }

        //Log to a file.
        FileStream stream = new FileStream("log.xml",FileMode.Append);
        mb.WriteMessage(stream);
        stream.Flush();
    }
}
<ServiceContract()> _
Public Class ForwardingService
    Private forwardingAddresses As List(Of IOutputChannel)

    <OperationContract()> _
    Public Sub ForwardMessage(ByVal m As Message)
        'Copy the message to a buffer.
        Dim mb As MessageBuffer = m.CreateBufferedCopy(65536)

        'Forward to multiple recipients.
        Dim channel As IOutputChannel
        For Each channel In forwardingAddresses
            Dim copy As Message = mb.CreateMessage()
            channel.Send(copy)
        Next channel

        'Log to a file.
        Dim stream As New FileStream("log.xml", FileMode.Append)
        mb.WriteMessage(stream)
        stream.Flush()

    End Sub
End Class

De MessageBuffer klas heeft andere leden die het vermelden waard zijn. De Close methode kan worden aangeroepen voor gratis resources wanneer de bufferinhoud niet meer nodig is. De BufferSize eigenschap retourneert de grootte van de toegewezen buffer. De MessageContentType eigenschap retourneert het MIME-inhoudstype van het bericht.

Toegang tot de berichttekst voor foutopsporing

Voor foutopsporing kunt u de ToString methode aanroepen om een weergave van het bericht als een tekenreeks op te halen. Deze weergave komt over het algemeen overeen met de manier waarop een bericht op de draad zou lijken als het is gecodeerd met de tekstcoderingsprogramma, behalve dat de XML beter zou zijn opgemaakt voor menselijke leesbaarheid. De enige uitzondering hierop is de hoofdtekst van het bericht. De hoofdtekst kan slechts eenmaal worden gelezen en ToString wijzigt de berichtstatus niet. Daarom heeft de ToString methode mogelijk geen toegang tot de hoofdtekst en kan deze een tijdelijke aanduiding vervangen (bijvoorbeeld '...'. of drie puntjes) in plaats van de hoofdtekst van het bericht. Gebruik daarom geen ToString logboekberichten als de hoofdtekst van de berichten belangrijk is.

Toegang tot andere berichtonderdelen

Er zijn verschillende eigenschappen beschikbaar voor toegang tot informatie over het andere bericht dan de hoofdinhoud. Deze kunnen echter niet worden aangeroepen zodra het bericht is gesloten:

  • De Headers eigenschap vertegenwoordigt de berichtkoppen. Zie de sectie 'Werken met kopteksten' verderop in dit onderwerp.

  • De Properties eigenschap vertegenwoordigt de berichteigenschappen, die stukjes benoemde gegevens zijn die zijn gekoppeld aan het bericht dat doorgaans niet wordt verzonden wanneer het bericht wordt verzonden. Zie de sectie 'Werken met eigenschappen' verderop in dit onderwerp.

  • De Version eigenschap geeft de SOAP- en WS-Adresseringsversie aan die is gekoppeld aan het bericht, of None als SOAP is uitgeschakeld.

  • De IsFault eigenschap retourneert true als het bericht een SOAP-foutbericht is.

  • De IsEmpty eigenschap retourneert true als het bericht leeg is.

U kunt de GetBodyAttribute(String, String) methode gebruiken om toegang te krijgen tot een bepaald kenmerk op het body wrapper-element (bijvoorbeeld <soap:Body>) dat is geïdentificeerd door een bepaalde naam en naamruimte. Als een dergelijk kenmerk niet wordt gevonden, null wordt deze geretourneerd. Deze methode kan alleen worden aangeroepen wanneer de Message status Gemaakt heeft (wanneer de hoofdtekst van het bericht nog niet is geopend).

Werken met kopteksten

Een Message kan een willekeurig aantal benoemde XML-fragmenten bevatten, kopteksten genoemd. Elk fragment wordt normaal gesproken toegewezen aan een SOAP-header. Headers worden geopend via de eigenschap van het Headers type MessageHeaders. MessageHeaders is een verzameling MessageHeaderInfo objecten en afzonderlijke headers kunnen worden geopend via de IEnumerable interface of via de indexeerfunctie. De volgende code bevat bijvoorbeeld de namen van alle headers in een Message.

public class MyService6 : IMyService
{
    public void PutData(Message m)
    {
        foreach (MessageHeaderInfo mhi in m.Headers)
        {
            Console.WriteLine(mhi.Name);
        }
    }

    public Message GetData()
    {
        throw new NotImplementedException();
    }
}
Public Class MyService6
    Implements IMyService

    Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
        Dim mhi As MessageHeaderInfo
        For Each mhi In m.Headers
            Console.WriteLine(mhi.Name)
        Next mhi

    End Sub


    Public Function GetData() As Message Implements IMyService.GetData
        Throw New NotImplementedException()

    End Function
End Class

Kopteksten toevoegen, verwijderen, zoeken

U kunt een nieuwe koptekst toevoegen aan het einde van alle bestaande headers met behulp van de Add methode. U kunt de Insert methode gebruiken om een header in te voegen bij een bepaalde index. Bestaande kopteksten worden verplaatst voor het ingevoegde item. Headers worden gerangschikt op basis van hun index en de eerste beschikbare index is 0. U kunt de verschillende CopyHeadersFrom methodeoverbelastingen gebruiken om headers van een ander Message exemplaar toe MessageHeaders te voegen. Sommige overbelastingen kopiëren één afzonderlijke koptekst, terwijl anderen ze allemaal kopiëren. Met de Clear methode worden alle headers verwijderd. Met de RemoveAt methode wordt een header in een bepaalde index verwijderd (waarbij alle headers erna worden verplaatst). Met de RemoveAll methode worden alle headers met een bepaalde naam en naamruimte verwijderd.

Haal een bepaalde header op met behulp van de FindHeader methode. Deze methode gebruikt de naam en naamruimte van de header om te zoeken en retourneert de index. Als de header meerdere keren voorkomt, wordt er een uitzondering gegenereerd. Als de header niet wordt gevonden, wordt -1 geretourneerd.

In het SOAP-headermodel kunnen headers een Actor waarde hebben die de beoogde ontvanger van de header aangeeft. De meest eenvoudige FindHeader overbelasting doorzoekt alleen headers die zijn bedoeld voor de ultieme ontvanger van het bericht. Met een andere overbelasting kunt u echter opgeven welke Actor waarden in de zoekopdracht worden opgenomen. Zie de SOAP-specificatie voor meer informatie.

Er wordt een CopyTo(MessageHeaderInfo[], Int32) methode geboden voor het kopiëren van headers van een MessageHeaders verzameling naar een matrix met MessageHeaderInfo objecten.

Als u toegang wilt tot de XML-gegevens in een koptekst, kunt u een XML-lezer aanroepen GetReaderAtHeader en retourneren voor de specifieke headerindex. Als u de inhoud van de koptekst wilt deserialiseren in een object, gebruikt GetHeader<T>(Int32) u of een van de andere overbelastingen. De meest eenvoudige overloads deserialiseren headers met behulp van de DataContractSerializer geconfigureerde op de standaard manier. Als u een andere serialisatiefunctie of een andere configuratie van de DataContractSerializerwilt gebruiken, gebruikt u een van de overbelastingen die een XmlObjectSerializer. Er zijn ook overbelastingen die de headernaam, naamruimte en eventueel een lijst met Actor waarden nemen in plaats van een index; dit is een combinatie van FindHeader en GetHeader.

Werken met eigenschappen

Een Message exemplaar kan een willekeurig aantal benoemde objecten van willekeurige typen bevatten. Deze verzameling wordt geopend via de eigenschap van het Properties type MessageProperties. De verzameling implementeert de IDictionary<TKey,TValue> interface en fungeert als een toewijzing van String naar Object. Normaal gesproken worden eigenschapswaarden niet rechtstreeks toegewezen aan een deel van het bericht op de kabel, maar bieden eerder verschillende hints voor berichtverwerking aan de verschillende kanalen in de WCF-kanaalstack of aan het CopyTo(MessageHeaderInfo[], Int32) serviceframework. Zie Voor een voorbeeld een overzicht van de architectuur voor gegevensoverdracht.

Overnemen van de berichtklasse

Als de ingebouwde berichttypen die zijn gemaakt, CreateMessage niet voldoen aan uw vereisten, maakt u een klasse die is afgeleid van de Message klasse.

De hoofdtekst van het bericht definiëren

Er bestaan drie primaire technieken voor toegang tot gegevens in een berichttekst: schrijven, lezen en kopiëren naar een buffer. Deze bewerkingen resulteren uiteindelijk in respectievelijk de OnWriteBodyContents, OnGetReaderAtBodyContentsen OnCreateBufferedCopy methoden die worden aangeroepen op uw afgeleide klasse van Message. De basisklasse Message garandeert dat slechts één van deze methoden wordt aangeroepen voor elk Message exemplaar en dat deze niet meer dan één keer wordt aangeroepen. De basisklasse zorgt er ook voor dat de methoden niet worden aangeroepen op een gesloten bericht. U hoeft de berichtstatus in uw implementatie niet bij te houden.

OnWriteBodyContents is een abstracte methode en moet worden geïmplementeerd. De eenvoudigste manier om de hoofdtekst van uw bericht te definiëren, is door deze methode te schrijven. Het volgende bericht bevat bijvoorbeeld 100.000 willekeurige getallen van 1 tot 20.

public class RandomMessage : Message
{
    override protected  void  OnWriteBodyContents(XmlDictionaryWriter writer)
    {
        Random r = new Random();
        for (int i = 0; i <100000; i++)
        {
            writer.WriteStartElement("number");
            writer.WriteValue(r.Next(1,20));
            writer.WriteEndElement();
        }
    }
    //code omitted…
Public Class RandomMessage
    Inherits Message

    Protected Overrides Sub OnWriteBodyContents( _
            ByVal writer As XmlDictionaryWriter)
        Dim r As New Random()
        Dim i As Integer
        For i = 0 To 99999
            writer.WriteStartElement("number")
            writer.WriteValue(r.Next(1, 20))
            writer.WriteEndElement()
        Next i

    End Sub
    ' Code omitted.

De OnGetReaderAtBodyContents() en OnCreateBufferedCopy methoden hebben standaard implementaties die voor de meeste gevallen werken. De standaard-implementatie aanroep OnWriteBodyContents, buffer de resultaten en werken met de resulterende buffer. In sommige gevallen is dit echter niet voldoende. In het voorgaande voorbeeld resulteert het lezen van het bericht in 100.000 XML-elementen die worden gebufferd, wat mogelijk niet wenselijk is. Mogelijk wilt u overschrijven OnGetReaderAtBodyContents() om een aangepaste XmlDictionaryReader afgeleide klasse te retourneren die willekeurige getallen verwerkt. U kunt vervolgens overschrijven OnWriteBodyContents om de lezer te gebruiken die door de OnGetReaderAtBodyContents() methode wordt geretourneerd, zoals wordt weergegeven in het volgende voorbeeld.

    public override MessageHeaders Headers
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override MessageProperties Properties
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override MessageVersion Version
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }
}

public class RandomMessage2 : Message
{
    override protected XmlDictionaryReader OnGetReaderAtBodyContents()
    {
    return new RandomNumbersXmlReader();
    }

    override protected void OnWriteBodyContents(XmlDictionaryWriter writer)
    {
        XmlDictionaryReader xdr = OnGetReaderAtBodyContents();
        writer.WriteNode(xdr, true);
    }
    public override MessageHeaders Headers
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override MessageProperties Properties
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override MessageVersion Version
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }
}

public class RandomNumbersXmlReader : XmlDictionaryReader
{
    //code to serve up 100000 random numbers in XML form omitted…

    Public Overrides ReadOnly Property Headers() As MessageHeaders
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property

    Public Overrides ReadOnly Property Properties() As MessageProperties
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property

    Public Overrides ReadOnly Property Version() As MessageVersion
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property
End Class

Public Class RandomMessage2
    Inherits Message

    Protected Overrides Function OnGetReaderAtBodyContents() As XmlDictionaryReader
        Return New RandomNumbersXmlReader()

    End Function


    Protected Overrides Sub OnWriteBodyContents(ByVal writer As XmlDictionaryWriter)
        Dim xdr As XmlDictionaryReader = OnGetReaderAtBodyContents()
        writer.WriteNode(xdr, True)

    End Sub

    Public Overrides ReadOnly Property Headers() As MessageHeaders
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property

    Public Overrides ReadOnly Property Properties() As MessageProperties
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property

    Public Overrides ReadOnly Property Version() As MessageVersion
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property
End Class

Public Class RandomNumbersXmlReader
    Inherits XmlDictionaryReader
    'code to serve up 100000 random numbers in XML form omitted

Op dezelfde manier wilt u mogelijk overschrijven OnCreateBufferedCopy om uw eigen MessageBuffer afgeleide klasse te retourneren.

Naast de inhoud van de berichttekst moet de afgeleide klasse van uw bericht ook de Versioneigenschappen en HeadersProperties eigenschappen overschrijven.

Houd er rekening mee dat als u een kopie van een bericht maakt, de kopie gebruikmaakt van de berichtkoppen uit het origineel.

Andere leden die kunnen worden overschreven

U kunt de OnWriteStartEnvelope, OnWriteStartHeadersen OnWriteStartBody methoden overschrijven om op te geven hoe de SOAP-envelop, SOAP-headers en soap-hoofdteksten beginnende tags worden geschreven. Deze komen normaal overeen met <soap:Envelope>, <soap:Header>en <soap:Body>. Deze methoden moeten normaal gesproken niets schrijven als de Version eigenschap retourneert None.

Notitie

De standaard implementatie van OnGetReaderAtBodyContents aanroepen OnWriteStartEnvelope en OnWriteStartBody voordat de resultaten worden aangeroepen en gebufferd OnWriteBodyContents . Kopteksten worden niet weggeschreven.

Overschrijf de OnWriteMessage methode om de manier te wijzigen waarop het hele bericht is samengesteld op basis van de verschillende onderdelen. De OnWriteMessage methode wordt aangeroepen vanuit WriteMessage en van de standaard OnCreateBufferedCopy implementatie. Houd er rekening mee dat het overschrijven WriteMessage geen best practice is. Het is beter om de juiste On methoden te overschrijven (bijvoorbeeld OnWriteStartEnvelope, OnWriteStartHeadersen OnWriteBodyContents.

Overschrijven om te overschrijven OnBodyToString hoe de hoofdtekst van uw bericht wordt weergegeven tijdens foutopsporing. De standaardwaarde is om deze weer te geven als drie puntjes (...). Houd er rekening mee dat deze methode meerdere keren kan worden aangeroepen wanneer de berichtstatus iets anders is dan Gesloten. Een implementatie van deze methode mag nooit leiden tot een actie die slechts één keer moet worden uitgevoerd (zoals lezen vanuit een stream die alleen doorsturend is).

Overschrijf de OnGetBodyAttribute methode om toegang tot kenmerken in het SOAP-hoofdtekstelement toe te staan. Deze methode kan een willekeurig aantal keren worden aangeroepen, maar het Message basistype garandeert dat deze alleen wordt aangeroepen wanneer het bericht de status Gemaakt heeft. Het is niet vereist om de status in een implementatie te controleren. De standaard implementatie retourneert nullaltijd, wat aangeeft dat er geen kenmerken zijn op het hoofdtekstelement.

Als uw Message object speciale opschoning moet uitvoeren wanneer de hoofdtekst van het bericht niet meer nodig is, kunt u overschrijven OnClose. De standaard implementatie doet niets.

De IsEmpty eigenschappen en IsFault eigenschappen kunnen worden overschreven. Standaard retourneren falsebeide .