Verwenden der Message-Klasse

Die Message Klasse ist für die Windows Communication Foundation (WCF). Die gesamte Kommunikation zwischen Clients und Diensten führt letztlich Message Instanzen gesendet und empfangen.

Sie würden normalerweise interagiert nicht mit der Message -Klasse direkt verwenden. Stattdessen werden WCF-Dienstmodellkonstrukte wie Datenverträge, Nachrichtenverträge und Vorgangsverträge zum Beschreiben von ein- und ausgehenden Nachrichten verwendet. In einigen erweiterten Szenarien jedoch Sie programmieren können, verwenden die Message -Klasse direkt verwenden. Beispielsweise möchten Sie verwenden die Message Klasse:

  • Wenn Sie eine alternative Methode zum Erstellen des Inhalts ausgehender Nachrichten (z. B. Erstellen einer Nachricht direkt aus einer Datei auf der Festplatte) statt des Serialisierens von .NET Framework-Objekten benötigen.

  • Wenn Sie eine alternative Methode zum Verwenden des Inhalts eingehender Nachrichten (z. B. zum Anwenden einer XSLT-Transformation auf den unformatierten XML-Inhalt) statt des Deserialisierens in .NET Framework-Objekte benötigen.

  • Wenn Sie Nachrichten allgemein und unabhängig vom Nachrichteninhalt bearbeiten müssen (z. B. zum Routen oder Weiterleiten von Nachrichten beim Erstellen eines Routers, Lastenausgleichsmoduls oder Veröffentlichen-Abonnieren-Systems).

Vor der Verwendung der Message Klasse, die sich mit vertraut machen, die WCF -Architektur für die Datenübertragung Übersicht über die Architektur von Data Transfer.

Ein Message ist ein allzweckcontainer für Daten, ihr Design folgt aber eng das Design einer Nachricht in das SOAP-Protokoll. Wie in SOAP verfügt eine Nachricht über einen Nachrichtentext und einen Header. Der Nachrichtentext enthält die tatsächlichen Nutzlastdaten, während die Header zusätzliche benannte Datencontainer enthalten. Die Regeln für das Lesen und Schreiben von Text und Headern sind unterschiedlich, so werden die Header immer im Arbeitsspeicher gepuffert, und der Zugriff ist beliebig oft in beliebiger Reihenfolge möglich, während der Text nur einmal gelesen und in einem Stream übertragen werden kann. Normalerweise werden in SOAP der Nachrichtentext dem SOAP-Text und die Nachrichtenheader den SOAP-Headern zugeordnet.

Verwenden der Meldungsklasse in Vorgängen

Sie können die Message Klasse als Eingabeparameter eines Vorgangs, der Rückgabewert eines Vorgangs oder beides. Wenn Message wird an einer beliebigen Stelle in einem Vorgang gelten die folgenden Einschränkungen:

  • Der Vorgang kann über keinen out-Parameter oder ref-Parameter verfügen.

  • Es kann nicht mehr als einen input-Parameter geben. Wenn der Parameter vorhanden ist, muss er entweder eine Nachricht oder ein Nachrichtenvertragstyp sein.

  • Der Rückgabetyp muss entweder void, Message oder ein Nachrichtenvertragstyp sein.

Das folgende Codebeispiel enthält einen gültigen Vorgangsvertrag.

[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

Erstellen grundlegender Nachrichten

Die Message -Klasse stellt statische CreateMessage Factory-Methoden, mit denen Sie grundlegende Nachrichten erstellen.

Alle CreateMessage Überladungen nehmen einen Versionsparameter vom Typ MessageVersion , der angibt, der SOAP und WS-Addressing-Versionen, für die Nachricht verwendet. Wenn Sie die gleichen Protokollversionen wie die eingehende Nachricht verwenden möchten, können Sie die IncomingMessageVersion Eigenschaft auf die OperationContext Instanz von abgerufen der Current Eigenschaft. Die meisten CreateMessage-Überladungen haben außerdem einen Zeichenfolgenparameter, der die für die Nachricht zu verwendende SOAP-Aktion angibt. Die Version kann auf None festgelegt werden, um die Generierung des SOAP-Umschlags zu deaktivieren; die Nachricht besteht nur aus dem Text.

Erstellen von Nachrichten aus Objekten

Die grundlegendste CreateMessage-Überladung, die nur eine Version und eine Aktion annimmt, erstellt eine Nachricht, die keinen Text enthält. Eine andere Überladung nimmt einen zusätzlichen Object Parameter; Dadurch wird eine Nachricht erstellt, deren Text die serialisierte Darstellung des angegebenen Objekts. Verwenden der DataContractSerializer mit den Standardeinstellungen für die Serialisierung. Wenn Sie ein anderes Serialisierungsprogramm verwenden möchten oder das DataContractSerializer anders konfiguriert werden soll, verwenden Sie die CreateMessage-Überladung, die auch einen XmlObjectSerializer-Parameter annimmt.

Sie können z. B. zum Zurückgeben eines Objekts in einer Nachricht den folgenden Code verwenden.

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

Erstellen von Nachrichten aus XML-Lesern

Gibt es CreateMessage -Überladungen nehmen ein XmlReader oder XmlDictionaryReader für den Text anstelle eines Objekts. In diesem Fall enthält der Text der Nachricht die XML, die aus dem Lesen des übergebenen XML-Readers resultiert. Der folgende Code gibt beispielsweise eine Nachricht mit aus einer XML-Datei gelesenem Textinhalt zurück:

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

Darüber hinaus stehen CreateMessage -Überladungen nehmen eine XmlReader oder XmlDictionaryReader , die gesamte Nachricht und nicht nur den Text darstellt. Diese Überladungen nehmen auch einen ganzzahligen maxSizeOfHeaders-Parameter an. Header werden immer in den Arbeitsspeicher gepuffert, sobald die Nachricht erstellt wurde, und dieser Parameter begrenzt die stattfindende Pufferung. Dieser Parameter sollte auf einen sicheren Wert festgelegt werden, wenn die XML von einer nicht vertrauenswürdigen Quelle stammt, um einen möglichen Denial-of-Service-Angriff zu vermeiden. Die SOAP-Version und die Version der WS-Adressierung der Nachricht, die der XML-Leser darstellt, müssen mit den durch den Versionsparameter angegebenen Versionen übereinstimmen.

Erstellen von Nachrichten mit dem Body Writer-Objekt

Eine CreateMessage-Überladung nimmt eine BodyWriter-Instanz an, um den Text der Nachricht zu beschreiben. Ein BodyWriter ist eine abstrakte Klasse, die abgeleitet werden kann, um das Erstellen von Nachrichtentexten anzupassen. Sie können eine eigene abgeleitete BodyWriter-Klasse erstellen, um Nachrichtentexte benutzerdefiniert zu beschreiben. Müssen Sie überschreiben die BodyWriter.OnWriteBodyContents Methode, die eine XmlDictionaryWriter; diese Methode ist verantwortlich für das Schreiben des Textes.

Body Writer-Objekte können gepuffert oder nicht gepuffert (gestreamt) sein. Gepufferte Body Writer-Objekte schreiben ihren Inhalt beliebig oft, während gestreamte Objekte den Inhalt nur einmal schreiben können. Die IsBuffered-Eigenschaft gibt an, ob ein Body Writer-Objekt gepuffert ist oder nicht. Sie können dies für das Body Writer-Objekt festlegen, indem Sie den geschützten BodyWriter-Konstruktor aufrufen, der einen booleschen isBuffered-Parameter annimmt. Body Writer-Objekte unterstützen das Erstellen eines gepufferten Body Writer-Objekts aus einem nicht gepufferten Body Writer-Objekt. Sie können die OnCreateBufferedCopy-Methode überschreiben, um diesen Prozess anzupassen. Standardmäßig wird ein Speicherpuffer verwendet, der das von OnWriteBodyContents zurückgegebene XML enthält. OnCreateBufferedCopy akzeptiert einen ganzzahligen maxBufferSize-Parameter. Wenn Sie diese Methode überschreiben, dürfen Sie keine Puffer erstellen, die diese maximale Größe überschreiten.

Die BodyWriter-Klasse bietet die WriteBodyContents-Methode und die CreateBufferedCopy-Methode, die im Grunde einfache Wrapper um die OnWriteBodyContents-Methode bzw. die OnCreateBufferedCopy-Methode sind. Diese Methoden führen eine Zustandsprüfung durch, um sicherzustellen, dass auf ein nicht gepuffertes Body Writer-Objekt höchstens einmal zugegriffen wird. Diese Methoden werden nur direkt aufgerufen, wenn benutzerdefinierte abgeleitete Message-Klassen erstellt werden, die auf BodyWriters basieren.

Erstellen von Fehlermeldungen

Sie können bestimmte CreateMessage-Überladungen verwenden, um SOAP-Fehlermeldungen zu erstellen. Die grundlegendste dieser Überladungen nimmt ein MessageFault -Objekt, das den Fehler beschreibt. Andere Überladungen werden aus Gründen der Benutzerfreundlichkeit bereitgestellt. Die erste solcher Überladungen nimmt einen FaultCode und eine Zeichenfolge der Ursache an und erstellt einen MessageFault mit MessageFault.CreateFault unter Verwendung dieser Informationen. Die andere Überladung nimmt eine Detailobjekt an und übergibt es auch zusammen mit dem Fehlercode und der Ursache an CreateFault. So gibt beispielsweise der folgende Vorgang einen Fehler zurück:

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

Extrahieren von Nachrichtentextdaten

Die Message-Klasse unterstützt mehrere Methoden zum Extrahieren von Informationen aus dem Text. Diese können in die folgenden Kategorien klassifiziert werden:

  • Einmaliges Abrufen des gesamten Nachrichtentexts in einen XML-Writer. Dies wird als bezeichnet Schreiben einer Nachricht.

  • Laufenlassen eines XML-Readers über den Nachrichtentext. Dies ermöglicht es Ihnen, später nach Bedarf Stück für Stück auf den Nachrichtentext zuzugreifen. Dies wird als bezeichnet Lesen einer Nachricht.

  • Die gesamte Nachricht, einschließlich des Texts in einem Speicherpuffer von kopiert werden die MessageBuffer Typ. Dies wird als bezeichnet Kopieren einer Nachricht.

Sie können unabhängig von der Zugriffsmethode nur einmal auf den Text einer Message zugreifen. Ein Nachrichtenobjekt verfügt über eine State-Eigenschaft, die anfänglich auf "Erstellt" festgelegt ist. Mit den drei zuvor beschriebenen Zugriffsmethoden wird der Zustand auf "Geschrieben", "Gelesen" bzw. "Kopiert" festgelegt. Darüber hinaus kann eine Close-Methode den Zustand auf "Geschlossen" festlegen, wenn der Inhalt des Nachrichtentexts nicht mehr benötigt wird. Auf den Nachrichtentext kann nur im Zustand "Erstellt" zugegriffen werden, und eine Rückkehr zu diesem Zustand ist nach einer Zustandsänderung nicht mehr möglich.

Schreiben von Nachrichten

Die WriteBodyContents(XmlDictionaryWriter) -Methode schreibt den Inhalt des Texts einer bestimmten Message Instanz mit einem angegebenen XML-Writer. Die WriteBody Methode ist identisch, abgesehen davon, dass der Inhalt des Nachrichtentexts in entsprechendes Wrapperelement eingeschlossen (z. B. soap:body>). Schließlich WriteMessage schreibt die gesamte Nachricht, einschließlich des umfassenden SOAP-Umschlags und der Header. Bei deaktiviertem SOAP (Version ist MessageVersion.None) wird von allen drei Methoden der gleiche Vorgang ausgeführt: Der Inhalt des Nachrichtentexts wird geschrieben.

Beispielsweise schreibt der folgende Code der Text einer eingehenden Nachricht in eine Datei.

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

Zwei zusätzliche Hilfsmethoden schreiben bestimmte SOAP-Startelement-Tags. Diese Methoden haben keinen Zugriff auf den Nachrichtentext, der Nachrichtenzustand wird also nicht geändert. Dazu gehören:

Rufen Sie zum Schreiben der jeweiligen Endelement-Tags WriteEndElement auf dem entsprechenden XML-Writer auf. Diese Methoden werden selten direkt aufgerufen.

Lesen von Nachrichten

Der einfachste Weg zum Lesen eines Nachrichtentexts besteht im Aufrufen GetReaderAtBodyContents. Sie erhalten eine XmlDictionaryReader , die Sie verwenden können, um den Nachrichtentext lesen. Beachten Sie, dass die Message in den Zustand "gelesen" übergeht, sobald GetReaderAtBodyContents aufgerufen wird, und wenn Sie nicht den XML-Reader verwenden.

Die GetBody -Methode können Sie den Zugriff auf den Nachrichtentext als typisiertes Objekt auch. Intern verwendet diese Methode GetReaderAtBodyContents, und damit auch die Nachricht in geht die MessageState Status (finden Sie unter der State Eigenschaft).

Es wird empfohlen, zum Überprüfen der IsEmpty Eigenschaft, in dem Fall der Nachrichtentext leer ist und GetReaderAtBodyContents löst ein InvalidOperationException. Darüber hinaus ist er eine empfangene Nachricht (z. B. die Antwort), Sie können auch überprüfen möchten IsFault, der angibt, ob die Nachricht einen Fehler enthält.

Die grundlegendste Überladung von GetBody deserialisiert den Nachrichtentext in eine Instanz eines Typs (angegeben durch den generischen Parameter) unter Verwendung einer DataContractSerializer mit den Standardeinstellungen und konfiguriert die MaxItemsInObjectGraph Kontingent deaktiviert. Wenn Sie ein anderes Serialisierungsmodul verwenden, oder konfigurieren möchten die DataContractSerializer in eine nicht standardmäßige Möglichkeit verwenden die GetBody Überladung mit einer XmlObjectSerializer.

Der folgende Code extrahiert beispielsweise Daten aus einem Nachrichtentext, der ein serialisiertes Person-Objekt enthält, und gibt den Namen der Person aus.

    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

Kopieren einer Nachricht in einen Puffer

Manchmal ist es erforderlich, mehrmals auf den Nachrichtentext zuzugreifen, beispielsweise um die gleiche Nachricht an mehrere Ziele als Teil eines Verleger-Abonnent-Systems weiterzuleiten. In diesem Fall ist es notwendig, die gesamte Nachricht (einschließlich des Textes) im Arbeitsspeicher zu puffern. Sie erreichen dies durch Aufrufen von CreateBufferedCopy(Int32). Diese Methode nimmt einen ganzzahligen Parameter an, der die maximale Puffergröße darstellt, und erstellt einen Puffer mit maximal dieser Größe. Legen Sie dafür einen sicheren Wert fest, wenn die Nachricht von einer nicht vertrauenswürdigen Quelle stammt.

Der Puffer wird zurückgegeben, als eine MessageBuffer Instanz. Es gibt mehrere Möglichkeiten, um auf Daten im Puffer zuzugreifen. Der einfachste Weg besteht im Aufrufen CreateMessage erstellen Message Instanzen aus dem Puffer.

Eine andere Methode Zugriff auf die Daten im Puffer ist das Implementieren der IXPathNavigable Schnittstelle, die MessageBuffer -Klasse implementiert, um das zugrunde liegende XML direkt zugreifen. Einige CreateNavigator Überladungen ermöglichen Ihnen die Erstellung System.Xml.XPath Navigatoren durch ein Knotenkontingent geschützten Begrenzen der Anzahl von XML-Knoten, die aufgerufen werden können. Dies hilft, Denial-of-Service-Angriffe auf der Grundlage von längerer Verarbeitungszeit zu verhindern. Dieses Kontingent ist standardmäßig deaktiviert. Einige CreateNavigator Überladungen können Sie angeben, wie Leerraum in der XML-Code behandelt werden soll mithilfe der XmlSpace Enumeration, wobei der Standard XmlSpace.None.

Eine letzte Methode Zugriff auf den Inhalt eines Nachrichtenpuffers ist das Schreiben des Inhalts in einen Stream mit WriteMessage.

Das folgende Beispiel demonstriert das Arbeiten mit einem MessageBuffer: Eine eingehende Nachricht wird an mehrere Empfänger weitergeleitet und anschließend in einer Datei protokolliert. Ohne Pufferung ist dies nicht möglich, da dann der Zugriff auf den Nachrichtentext nur einmal möglich ist.

[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

Die MessageBuffer-Klasse verfügt über andere erwähnenswerte Member. Die Close Methode kann Ressourcen freigibt, aufgerufen werden, wenn der Pufferinhalt nicht mehr benötigt werden. Die BufferSize -Eigenschaft gibt die Größe des reservierten Puffers zurück. Die MessageContentType -Eigenschaft gibt den MIME-Inhaltstyp der Nachricht zurück.

Zugreifen auf den Nachrichtentext zum Debuggen

Für das Debuggen rufen Sie die ToString Methode, um eine Darstellung der Nachricht als Zeichenfolge abzurufen. Diese Darstellung stimmt im Allgemeinen mit der Darstellung einer Nachricht überein, wenn sie mit dem Textencoder codiert worden wäre, außer dass die XML zur Lesbarkeit besser formatiert wäre. Die einzige Ausnahme ist der Nachrichtentext. Der Text kann nur einmal gelesen werden, und ToString ändert den Nachrichtenzustand nicht. Aus diesem Grund die ToString Methode möglicherweise nicht auf den Text zuzugreifen und möglicherweise durch einen Platzhalter (z. B. "..." ersetzt oder drei Punkte) ersetzt. Verwenden Sie deswegen ToString nicht zum Protokollieren von Nachrichten, wenn der Textinhalt der Nachrichten wichtig ist.

Zugreifen auf andere Nachrichtenteile

Für den Zugriff auf andere Informationen zur Nachricht als den Textinhalt werden verschiedene Eigenschaften bereitgestellt. Diese können jedoch nicht aufgerufen werden, wenn die Nachricht geschlossen wurde:

  • Die Headers Eigenschaft stellt die Nachrichtenheader dar. Weitere Informationen finden Sie im Abschnitt "Arbeiten mit Headern" weiter unten in diesem Thema.

  • Die Properties Eigenschaft darstellt, die Eigenschaften der Nachricht, die Datenelemente benannte an die Nachricht angehängt, die nicht in der Regel ausgegeben, wenn die Nachricht gesendet wird. Weitere Informationen finden Sie im Abschnitt "Arbeiten mit Eigenschaften" weiter unten in diesem Thema.

  • Die Version -Eigenschaft gibt an, die der Nachricht zugeordnete SOAP und WS-Addressing-Version oder None wenn SOAP deaktiviert ist.

  • Die IsFault gibt true Wenn die Nachricht eine SOAP-Fehlermeldung.

  • Die IsEmpty gibt true , wenn die Nachricht leer ist.

Sie können der GetBodyAttribute(String, String) Methode, um ein bestimmtes Attribut im textwrapperelement (z. B. <soap:Body>) mit einem bestimmten Namen und Namespace identifiziert. Wenn ein solches Attribut nicht gefunden wurde, wird null zurückgegeben. Diese Methode kann nur dann aufgerufen werden, wenn sich die Message im Zustand "Erstellt" befindet (wenn noch nicht auf den Nachrichtentext zugegriffen wurde).

Arbeiten mit Headern

Ein Message kann eine beliebige Anzahl benannter XML-Fragmente bezeichnet enthalten Header. Jedes Fragment wird normalerweise einem SOAP-Header zugeordnet. Header erfolgt über die Headers Eigenschaft vom Typ MessageHeaders. MessageHeaders ist eine Sammlung von MessageHeaderInfo Objekte und auf einzelne Header können über zugegriffen werden die IEnumerable Schnittstelle oder durch den Indexer. Im folgenden Code werden z. B. die Namen aller Header in einer Message aufgelistet.

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

Hinzufügen, Entfernen und Suchen von Headern

Sie können einen neuen Header hinzuzufügen, am Ende aller vorhandenen Header mit den Add Methode. Sie können die Insert Methode, um einen Header an einem bestimmten Index einzufügen. Vorhandene Header werden für das eingefügte Element verschoben. Header werden nach ihrem Index geordnet, dabei ist der erste verfügbare Index 0. Sie können mithilfe der verschiedenen CopyHeadersFrom überladene Methoden zum Hinzufügen von Headern aus einer anderen Message oder MessageHeaders Instanz. Einige Überladungen kopieren einen einzelnen Header, während andere alle Header kopieren. Die Clear -Methode entfernt alle Header. Die RemoveAt -Methode entfernt einen Header an einem bestimmten Index (alle nachfolgenden Header dahinter). Die RemoveAll -Methode entfernt alle Header mit einem bestimmten Namen und Namespace.

Abrufen einer bestimmten Headers mit dem FindHeader Methode. Diese Methode nimmt den Namen und Namespace des zu suchenden Headers an, und gibt seinen Index zurück. Wenn der Header mehrmals auftritt, wird eine Ausnahme ausgelöst. Wenn der Header nicht gefunden wurde, wird -1 zurückgegeben.

Im SOAP-Headermodell können Header einen Actor-Wert aufweisen, der den gewünschten Empfänger des Headers angibt. Die grundlegendste FindHeader-Überladung sucht nur Header, die für den letzten Empfänger der Nachricht vorgesehen sind. Mit einer anderen Überladung können Sie jedoch angeben, welche Actor-Werte in der Suche enthalten sind. Weitere Informationen finden Sie unter zur SOAP-Spezifikation.

Ein [CopyTo (MessageHeaderInfo<xref:System.ServiceModel.Channels.MessageHeaders.CopyTo%28System.ServiceModel.Channels.MessageHeaderInfo%5B%5D%2CSystem.Int32%29> Methode dient zum Kopieren von Headern aus einer MessageHeaders Auflistung in ein Array von MessageHeaderInfo Objekte.

Sie können für den Zugriff auf die XML-Daten in einem Header, Aufrufen GetReaderAtHeader und einen XML-Leser für den Headerindex zurückgeben. Wenn Sie den Inhalt des Headers in ein Objekt zu deserialisieren möchten, verwenden GetHeader<T>(Int32) oder eine der anderen Überladungen. Die grundlegendsten Überladungen Deserialisieren Header mit der DataContractSerializer konfiguriert, die in der Standard-Methode. Wenn Sie ein anderes Serialisierungsprogramm oder eine andere Konfiguration von DataContractSerializer verwenden möchten, nutzen Sie eine der Überladungen, die ein XmlObjectSerializer akzeptieren. Einige Überladungen akzeptieren auch den Headernamen, Namespace und optional eine Liste von Actor-Werte anstelle eines Index; dies ist eine Kombination von FindHeader und GetHeader.

Arbeiten mit Eigenschaften

Eine Message-Instanz kann eine beliebige Anzahl von benannten Objekten beliebiger Typen enthalten. Auf diese Auflistung wird über die Properties-Eigenschaft vom Typ MessageProperties zugegriffen. Die Auflistung implementiert die IDictionary<TKey,TValue> -Schnittstelle und fungiert als Zuordnung von String auf Object.</TKey, TValue> Eigenschaftswerte nicht direkt an einen beliebigen Teil der Nachricht zuordnen normalerweise bieten vielmehr verschiedene nachrichtenverarbeitungshinweise für die Kanäle in der WCF Kanalstapel oder die [CopyTo (MessageHeaderInfo<xref:System.ServiceModel.Channels.MessageHeaders.CopyTo%28System.ServiceModel.Channels.MessageHeaderInfo%5B%5D%2CSystem.Int32%29> dienstframework. Ein Beispiel finden Sie unter Data Transfer Architectural Overview.

Erben von der Meldungsklasse

Erstellen Sie eine von der CreateMessage-Klasse abgeleitete Klasse, wenn die mit Message erstellten integrierten Nachrichtentypen nicht den Anforderungen entsprechen.

Definieren des Nachrichtentextinhalts

Für den Zugriff auf Daten innerhalb eines Nachrichtentexts gibt es drei grundlegende Verfahren: Schreiben, Lesen und Kopieren in einen Puffer. Diese Vorgänge letztlich in die OnWriteBodyContents, OnGetReaderAtBodyContents, und OnCreateBufferedCopy Methoden, die aufgerufen wird, bzw. in einer abgeleiteten Klasse von Message. Die Message-Basisklasse stellt sicher, dass für jede Message-Instanz nur eine dieser Methoden aufgerufen wird und dieser Vorgang jeweils nur einmal stattfindet. Die Basisklasse stellt auch sicher, dass die Methoden nicht für eine geschlossene Nachricht aufgerufen werden. Es ist nicht erforderlich, den Nachrichtenzustand in der Implementierung zu verfolgen.

OnWriteBodyContents ist eine abstrakte Methode und muss implementiert werden. Die grundlegendste Weise zum Definieren des Textinhalts der Nachricht ist, mit dieser Methode zu schreiben. Zum Beispiel enthält die folgende Nachricht 100.000 Zufallszahlen von 1 bis 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.

Die OnGetReaderAtBodyContents-Methode und die OnCreateBufferedCopy-Methode verfügen über Standardimplementierungen, die in den meisten Fällen funktionieren. Die Standardimplementierungen rufen OnWriteBodyContents auf, speichern die Ergebnisse im Puffer und arbeiten mit dem resultierenden Puffer. In einigen Fällen genügt dies möglicherweise nicht. In vorhergehenden Beispiel führt das Lesen der Nachricht dazu, dass 100.000 XML-Elemente im Puffer gespeichert werden, was unter Umständen nicht wünschenswert ist. Es kann empfehlenswert sein, OnGetReaderAtBodyContents zu überschreiben, um eine benutzerdefinierte abgeleitete XmlDictionaryReaderKlasse zurückzugeben, die Zufallszahlen bereitstellt. Sie können dann OnWriteBodyContents überschreiben, um den von der OnGetReaderAtBodyContents-Eigenschaft zurückgegebenen Leser zu verwenden, wie im folgenden Beispiel dargestellt.

    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

Auf ähnliche Weise können Sie OnCreateBufferedCopy überschreiben, um eine eigene abgeleitete MessageBuffer-Klasse zurückzugeben.

Zusätzlich zum Bereitstellen von Nachrichtentextinhalt muss die abgeleitete Nachrichtenklasse auch die Version-Eigenschaft, die Headers-Eigenschaft und die Properties-Eigenschaft überschreiben.

Beachten Sie, dass beim Erstellen der Kopie einer Nachricht die Kopie die Nachrichtenheader aus dem Original verwendet.

Andere Member, die überschrieben werden können

Sie können außer Kraft setzen der OnWriteStartEnvelope, OnWriteStartHeaders, und OnWriteStartBody Methoden, um anzugeben, wie die SOAP-Umschlag, SOAP-Header und SOAP-Textelement-Starttags geschrieben werden. Diese entsprechen normalerweise <soap:Envelope>``<soap:Body>, <soap:Header> und . Diese Methoden sollten normalerweise nichts schreiben, wenn die Version-Eigenschaft MessageVersion.None zurückgibt.

Hinweis

Die Standardimplementierung von OnGetReaderAtBodyContents ruft OnWriteStartEnvelope und OnWriteStartBody auf, bevor OnWriteBodyContents aufgerufen wird und die Ergebnisse im Puffer gespeichert werden. Header werden nicht geschrieben.

Überschreiben Sie die OnWriteMessage Methode, um die gesamte Nachricht erstellt wird, wie aus den verschiedenen Teilen ändern. Die OnWriteMessage aufgerufen, aus WriteMessage und aus der OnCreateBufferedCopy Implementierung. Beachten Sie, dass das Überschreiben WriteMessage wird nicht empfohlen. Es ist besser, überschreiben Sie die entsprechende On Methoden (z. B. OnWriteStartEnvelope, OnWriteStartHeaders, und OnWriteBodyContents.

Überschreiben Sie OnBodyToString überschreiben, wie der Nachrichtentext während des Debuggens dargestellt wird. Der Standard ist die Darstellung als drei Punkte ("…"). Diese Methode kann mehrfach ausgerufen werden, wenn der Nachrichtenzustand nicht "Geschlossen" lautet. Eine Implementierung dieser Methode sollte nie eine Aktion verursachen, die nur einmal ausgeführt werden muss (wie das Lesen eines Vorwärtsstreams).

Überschreiben Sie die OnGetBodyAttribute Methode, um den Zugriff auf Attribute im SOAP-Textelement zuzulassen. Diese Methode kann beliebig oft aufgerufen werden, der Message-Basistyp stellt jedoch sicher, dass sie nur dann aufgerufen wird, wenn der Zustand der Nachricht "Erstellt" lautet. Es ist nicht erforderlich, den Zustand in einer Implementierung zu überprüfen. Die Standardimplementierung gibt immer null zurück, was bedeutet, dass im Textelement keine Attribute vorhanden sind.

Wenn Ihre Message -Objekt eine spezielle Bereinigung ausführen, wenn der Nachrichtentext nicht mehr benötigt wird, können Sie überschreiben OnClose. Bei der Standardimplementierung wird keine Aktion ausgeführt.

Die IsEmpty-Eigenschaft und die IsFault-Eigenschaft können überschrieben werden. Standardmäßig geben beide false zurück.