Datenübertragungsarchitektur - ÜbersichtData Transfer Architectural Overview

Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) kann als Messaginginfrastruktur betrachtet werden. can be thought of as a messaging infrastructure. Damit können Nachrichten empfangen, verarbeitet und für weitere Aktionen an Benutzercode verteilt werden, oder es können Nachrichten anhand von Daten des Benutzercodes erstellt und an ein Ziel übergeben werden.It can receive messages, process them, and dispatch them to user code for further action, or it can construct messages from data given by user code and deliver them to a destination. In diesem Thema, das sich an fortgeschrittene Entwickler richtet, wird die Architektur zur Verarbeitung von Nachrichten und der darin enthaltenen Daten beschrieben.This topic, which is intended for advanced developers, describes the architecture for handling messages and the contained data. Eine einfachere, funktionsbezogene Betrachtung zum Senden und Empfangen von Daten finden Sie unter Specifying Data Transfer in Service Contracts.For a simpler, task-oriented view of how to send and receive data, see Specifying Data Transfer in Service Contracts.

Hinweis

In diesem Thema werden die WCFWCF -Implementierungsdetails, die nicht sichtbar sind, anhand des WCFWCF -Objektmodells erläutert.This topic discusses WCFWCF implementation details that are not visible by examining the WCFWCF object model. Zwei Hinweise im Hinblick auf die dokumentierten Implementierungsdetails sind wichtig.Two words of caution are in order with regard to documented implementation details. Zunächst einmal sind die Beschreibungen vereinfacht dargestellt; die tatsächliche Implementierung ist möglicherweise aufgrund von Optimierungen oder aus anderen Gründen komplexer.First, the descriptions are simplified; actual implementation may be more complex due to optimizations or other reasons. Zweitens: Sie sollten sich nie auf bestimmte Implementierungsdetails verlassen, auch nicht auf die dokumentierten, da sich diese ohne Vorankündigung von Version zu Version oder sogar innerhalb eines Service Release ändern können.Second, you should never rely on specific implementation details, even documented ones, because these may change without notice from version to version or even in a servicing release.

BasisarchitekturBasic Architecture

Die zentrale Komponente der WCFWCF -Nachrichtenverarbeitungsfunktionen ist die Message -Klasse, die unter Using the Message Class.At the core of WCFWCF message-handling capabilities is the Message class, which is described in detail in Using the Message Class. Die Laufzeitkomponenten von WCFWCF können in zwei Hauptteile unterteilt werden: den Kanalstapel und das Dienstframework, wobei die Message -Klasse den Verbindungspunkt darstellt.The run-time components of WCFWCF can be divided into two major parts: the channel stack and the service framework, with the Message class being the connection point.

Der Kanalstapel ist für die Konvertierung zwischen einer gültigen Message -Instanz und einer Aktion verantwortlich, die dem Senden und Empfangen von Nachrichtendaten entspricht.The channel stack is responsible for converting between a valid Message instance and some action that corresponds to the sending or receiving of message data. Auf der Absenderseite verwendet der Kanalstapel eine gültige Message -Instanz und führt nach einigen Verarbeitungsschritten eine Aktion aus, die logisch dem Senden der Nachricht entspricht.On the sending side, the channel stack takes a valid Message instance and, after some processing, performs some action that logically corresponds to sending the message. Bei der Aktion kann es sich um das Senden von TCP- oder HTTP-Paketen, das Senden der Nachricht an die Warteschlange von Message Queuing, das Schreiben der Nachricht in eine Datenbank, das Speichern in einer Dateifreigabe oder, je nach Implementierung, um eine andere Aktion handeln.The action may be sending TCP or HTTP packets, queuing the message in Message Queuing, writing the message to a database, saving it to a file share, or any other action, depending on the implementation. Die am häufigsten verwendete Aktion ist das Senden der Nachricht über ein Netzwerkprotokoll.The most common action is sending the message over a network protocol. Auf der Empfängerseite geschieht genau das Gegenteil: Eine Aktion wird erkannt (dabei kann es sich um das Eintreffen von TCP- oder HTTP-Paketen oder eine andere Aktion handeln) und nach der Verarbeitung vom Kanalstapel in eine gültige Message -Instanz umgewandelt.On the receive side, the opposite happens—an action is detected (which may be TCP or HTTP packets arriving or any other action), and, after processing, the channel stack converts this action into a valid Message instance.

Sie können WCFWCF verwenden, indem Sie die Message -Klasse und den Kanalstapel direkt verwenden.You can use WCFWCF by using the Message class and the channel stack directly. Dies ist jedoch schwierig und zeitaufwändig.However, doing so is difficult and time-consuming. Darüber hinaus bietet das Message -Objekt keine Metadatenunterstützung, sodass Sie keine WCFWCF -Clients mit starker Typisierung generieren können, wenn Sie WCFWCF auf diese Weise verwenden.Additionally, the Message object provides no metadata support, so you cannot generate strongly typed WCFWCF clients if you use WCFWCF in this manner.

Deshalb bietet WCFWCF ein Dienstframework mit einem einfach zu bedienenden Programmiermodell, das Sie zum Erstellen und Empfangen von Message -Objekten verwenden können.Therefore, WCFWCF includes a service framework that provides an easy-to-use programming model that you can use to construct and receive Message objects. Das Dienstframework ordnet den .NET Framework.NET Framework -Typen über Dienstverträge Dienste zu und sendet Nachrichten an Benutzervorgänge, bei denen es sich einfach um .NET Framework.NET Framework -Methoden handelt, die mit dem OperationContractAttribute -Attribut gekennzeichnet sind (weitere Informationen finden Sie unter Designing Service Contracts).The service framework maps services to .NET Framework.NET Framework types through the notion of service contracts, and dispatches messages to user operations that are simply .NET Framework.NET Framework methods marked with the OperationContractAttribute attribute (for more details, see Designing Service Contracts). Diese Methoden verwenden möglicherweise Parameter und Rückgabewerte.These methods may have parameters and return values. Auf der Dienstseite wandelt das Dienstframework eingehende Message -Instanzen in Parameter um und Rückgabewerte in ausgehende Message -Instanzen.On the service side, the service framework converts incoming Message instances into parameters and converts return values into outgoing Message instances. Auf der Clientseite findet das Gegenteil statt.On the client side, it does the opposite. Betrachten Sie z. B. den nachfolgenden FindAirfare -Vorgang.For example, consider the FindAirfare operation below.

[ServiceContract]
public interface IAirfareFinderService
{
    [OperationContract]
    int FindAirfare(string FromCity, string ToCity, out bool IsDirectFlight);
}
<ServiceContract()> _
    Public Interface IAirfareFinderService

    <OperationContract()> _
    Function FindAirfare(ByVal FromCity As String, _
    ByVal ToCity As String, ByRef IsDirectFlight As Boolean) As Integer

End Interface

Nehmen wir an, auf dem Client wird FindAirfare aufgerufen.Suppose FindAirfare is called on the client. Das Dienstframework auf dem Client wandelt die FromCity -Parameter und ToCity - Parameter in eine ausgehende Message -Instanz um und übergibt diese an den zu sendenden Kanalstapel.The service framework on the client converts the FromCity and ToCity parameters into an outgoing Message instance and passes it to the channel stack to be sent.

Wenn auf der Dienstseite eine Message -Instanz vom Kanalstapel ankommt, extrahiert das Dienstframework die relevanten Daten aus der Nachricht, um die FromCity -Parameter und ToCity -Parameter zu füllen, und ruft dann die dienstseitige FindAirfare -Methode auf.On the service side, when a Message instance arrives from the channel stack, the service framework extracts the relevant data from the message to populate the FromCity and ToCity parameters and then calls the service-side FindAirfare method. Wenn die Methode zurückgegeben wird, verwendet das Dienstframework den zurückgegebenen Ganzzahlwert und den IsDirectFlight -Ausgabeparameter und erstellt eine Message -Objektinstanz, die diese Informationen enthält.When the method returns, the service framework takes the returned integer value and the IsDirectFlight output parameter and creates a Message object instance that contains this information. Es übergibt dann die Message -Instanz an den Kanalstapel, damit sie an den Client zurückgesendet wird.It then passes the Message instance to the channel stack to be sent back to the client.

Auf der Clientseite entsteht eine Message -Instanz, die die Antwortmeldung vom Kanalstapel enthält.On the client side, a Message instance that contains the response message emerges from the channel stack. Das Dienstframework extrahiert den Rückgabewert und den IsDirectFlight -Wert und gibt diese an den Aufrufer des Clients zurück.The service framework extracts the return value and the IsDirectFlight value and returns these to the caller of the client.

NachrichtenklasseMessage Class

Die Message -Klasse soll eine abstrakte Darstellung einer Nachricht sein, ihre Struktur ist jedoch eng mit der SOAP-Nachricht verbunden.The Message class is intended to be an abstract representation of a message, but its design is strongly tied to the SOAP message. Eine Message enthält drei Hauptinformationen: einen Nachrichtentext, Nachrichtenheader und Nachrichteneigenschaften.A Message contains three major pieces of information: a message body, message headers, and message properties.

NachrichtentextMessage Body

Der Nachrichtentext soll die tatsächliche Datennutzlast der Nachricht darstellen.The message body is intended to represent the actual data payload of the message. Der Nachrichtentext wird immer als XML-Infoset dargestellt.The message body is always represented as an XML Infoset. Dies bedeutet nicht, dass alle in WCFWCF erstellten oder empfangenen Nachrichten das XML-Format aufweisen müssen.This does not mean that all messages created or received in WCFWCF must be in XML format. Es obliegt dem Kanalstapel, zu entscheiden, wie der Nachrichtentext interpretiert wird.It is up to the channel stack to decide how to interpret the message body. Er wird eventuell als XML ausgegeben, in ein anderes Format konvertiert oder sogar ganz weggelassen.It may emit it as XML, convert it to some other format, or even omit it entirely. Bei den meisten, von WCFWCF bereitgestellten Bindungen wird der Nachrichtentext als XML-Inhalt im Textabschnitt eines SOAP-Umschlags dargestellt.Of course, with most of the bindings WCFWCF supplies, the message body is represented as XML content in the body section of a SOAP envelope.

Ihnen sollte auf jeden Fall bewusst sein, dass die Message -Klasse nicht unbedingt einen Puffer mit XML-Daten enthält, die den Textkörper darstellen.It is important to realize that the Message class does not necessarily contain a buffer with XML data representing the body. Message enthält zwar ein XML-Infoset, dieser Infoset wurde jedoch eventuell dynamisch erstellt und ist im Speicher gar nicht physisch vorhanden.Logically, Message contains an XML Infoset, but this Infoset may be dynamically constructed and may never physically exist in memory.

Einfügen von Daten in den NachrichtentextPutting Data into the Message Body

Es gibt kein einheitliches Verfahren zum Einfügen von Daten in einen Nachrichtentext.There is no uniform mechanism to put data into a message body. Die Message -Klasse bietet eine abstrakte Methode, OnWriteBodyContents(XmlDictionaryWriter), die XmlDictionaryWriterakzeptiert.The Message class has an abstract method, OnWriteBodyContents(XmlDictionaryWriter), which takes an XmlDictionaryWriter. Jede Unterklasse der Message -Klasse ist für das Überschreiben dieser Methode und Schreiben ihres eigenen Inhalts verantwortlich.Each subclass of the Message class is responsible for overriding this method and writing out its own contents. Der Nachrichtentext enthält den XML-Infoset, der OnWriteBodyContent erzeugt, logisch.The message body logically contains the XML Infoset that OnWriteBodyContent produces. Betrachten Sie beispielsweise die folgende Message -Unterklasse:For example, consider the following Message subclass.

public class AirfareRequestMessage : Message
{
    public string fromCity = "Tokyo";
    public string toCity = "London";
    //code omitted�
    protected override void OnWriteBodyContents(XmlDictionaryWriter w)
    {
        w.WriteStartElement("airfareRequest");
        w.WriteElementString("from", fromCity);
        w.WriteElementString("to", toCity);
        w.WriteEndElement();
    }

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

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

    public override bool IsEmpty
    {
        get
        {
            return base.IsEmpty;
        }
    }

    public override bool IsFault
    {
        get
        {
            return base.IsFault;
        }
    }
}
Public Class AirfareRequestMessage
    Inherits Message

    Public fromCity As String = "Tokyo"
    Public toCity As String = "London"
    ' Code omitted�
    Protected Overrides Sub OnWriteBodyContents(ByVal w As XmlDictionaryWriter)
        w.WriteStartElement("airfareRequest")
        w.WriteElementString("from", fromCity)
        w.WriteElementString("to", toCity)
        w.WriteEndElement()
    End Sub

    Public Overrides ReadOnly Property Version() As MessageVersion
        Get
            Throw New NotImplementedException("The method 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 Headers() As MessageHeaders
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property


    Public Overrides ReadOnly Property IsEmpty() As Boolean
        Get
            Return MyBase.IsEmpty
        End Get
    End Property

    Public Overrides ReadOnly Property IsFault() As Boolean
        Get
            Return MyBase.IsFault
        End Get
    End Property
End Class

Physisch enthält eine AirfareRequestMessage -Instanz nur zwei Zeichenfolgen ("fromCity" und "toCity").Physically, an AirfareRequestMessage instance contains only two strings ("fromCity" and "toCity"). Logisch enthält die Nachricht jedoch den folgenden XML-Infoset:However, logically the message contains the following XML infoset:

<airfareRequest>  
    <from>Tokyo</from>  
    <to>London</to>  
</airfareRequest>  

Selbstverständlich würden Sie im Normalfall keine Nachrichten auf diese Weise erstellen, da Sie zum Erstellen einer Nachricht wie der vorhergehenden aus Vorgangsvertragsparametern das Dienstframework verwenden können.Of course, you would normally not create messages in this manner, because you can use the service framework to create a message like the preceding one from operation contract parameters. Darüber hinaus bietet die Message -Klasse statische CreateMessage -Methoden, mit denen Sie Nachrichten mit häufig verwendeten Inhaltstypen erstellen können: eine leere Nachricht, eine Nachricht mit einem mit DataContractSerializerXML-serialisierten Objekt, eine Nachricht, die einen SOAP-Fehler enthält, eine Nachricht, die durch XmlReaderdargestelltes XML enthält usw.Additionally, the Message class has static CreateMessage methods that you can use to create messages with common types of content: an empty message, a message that contains an object serialized to XML with the DataContractSerializer, a message that contains a SOAP fault, a message that contains XML represented by an XmlReader, and so on.

Abrufen von Daten aus einem NachrichtentextGetting Data from a Message Body

Sie können die in einem Nachrichtentext gespeicherten Daten auf zwei Arten extrahieren:You can extract the data stored in a message body in two main ways:

  • Sie können den gesamten Nachrichtentext einmalig abrufen, indem Sie die WriteBodyContents(XmlDictionaryWriter) -Methode aufrufen und einen XML-Writer übergeben.You can get the entire message body at one time by calling the WriteBodyContents(XmlDictionaryWriter) method and passing in an XML writer. Der vollständige Nachrichtentext wird an diesen Writer ausgeschrieben.The complete message body is written out to this writer. Das einmalige Abrufen des gesamten Nachrichtentexts wird auch als Schreiben einer Nachrichtbezeichnet.Getting the entire message body at one time is also called writing a message. Das Schreiben wird hauptsächlich beim Senden der Nachrichten vom Kanalstapel übernommen. Ein Teil des Kanalstapels erhält in der Regel Zugriff auf den gesamten Nachrichtentext, codiert diesen und sendet ihn.Writing is done primarily by the channel stack when sending messages—some part of the channel stack will usually get access to the entire message body, encode it, and send it.

  • Eine weitere Methode zum Abrufen von Informationen aus dem Nachrichtentext besteht im Aufrufen von GetReaderAtBodyContents() und Abrufen eines XML-Lesers.Another way to get information out of the message body is to call GetReaderAtBodyContents() and get an XML reader. Auf den Nachrichtentext kann dann nacheinander nach Bedarf zugegriffen werden, indem Methoden im Reader aufgerufen werden.The message body can then be accessed sequentially as needed by calling methods on the reader. Das Abrufen des Nachrichtentexts Stück für Stück wird auch als Lesen einer Nachrichtbezeichnet.Getting the message body piece-by-piece is also called reading a message. Das Lesen der Nachricht wird hauptsächlich beim Empfangen von Nachrichten vom Dienstframework verwendet.Reading the message is primarily used by the service framework when receiving messages. Wenn z.&#160;B. DataContractSerializer verwendet wird, lässt das Dienstframework einen XML-Leser über den Nachrichtentext laufen und übergibt ihn dann an das Deserialisierungsmodul, das dann mit dem Lesen der Nachricht Element für Element und mit dem Erstellen des entsprechenden Objektdiagramms beginnt.For example, when the DataContractSerializer is in use, the service framework will get an XML reader over the body and pass it to the deserialization engine, which will then start reading the message element-by-element and constructing the corresponding object graph.

Ein Nachrichtentext kann nur einmalig abgerufen werden.A message body can be retrieved only once. Dies macht es möglich, mit Vorwärtsstreams zu arbeiten.This makes it possible to work with forward-only streams. So können Sie z.&#160;B. eine OnWriteBodyContents(XmlDictionaryWriter) -Überschreibung schreiben, die aus FileStream liest und die Ergebnisse als XML-Infoset zurückgibt.For example, you can write an OnWriteBodyContents(XmlDictionaryWriter) override that reads from a FileStream and returns the results as an XML Infoset. Sie müssen nie zum Anfang der das "Zurückspulen".You will never need to "rewind" to the beginning of the file.

Die WriteBodyContents -Methode und GetReaderAtBodyContents -Methode prüfen einfach, ob der Nachrichtentext schon zuvor einmal abgerufen wurde, und rufen dann OnWriteBodyContents oder OnGetReaderAtBodyContentsauf.The WriteBodyContents and GetReaderAtBodyContents methods simply check that the message body has never been retrieved before, and then call OnWriteBodyContents or OnGetReaderAtBodyContents, respectively.

Nachrichtenverwendung in WCFMessage Usage in WCF

Die meisten Nachrichten können entweder als ausgehend (diejenigen, die vom Dienstframework zum Senden vom Kanalstapel erstellt werden) oder eingehend (diejenigen, die vom Kanalstapel eingehen und vom Dienstframework interpretiert werden) klassifiziert werden.Most messages can be classified as either outgoing (those that are created by the service framework to be sent by the channel stack) or incoming (those that arrive from the channel stack and are interpreted by the service framework). Weiterhin kann der Kanalstapel entweder im gepufferten oder Streamingmodus operieren.Furthermore, the channel stack can operate in either buffered or streaming mode. Das Dienstframework kann auch ein per Streaming oder nicht per Streaming übertragenes Programmiermodell verfügbar machen.The service framework may also expose a streamed or nonstreamed programming model. Dies führt zu den in der folgenden Tabelle aufgelisteten Fällen, zusammen mit vereinfachten Details ihrer Implementierung.This leads to the cases listed in the following table, along with simplified details of their implementation.

NachrichtentypMessage type Textdaten in NachrichtBody data in message Write-Implementierung (OnWriteBodyContents)Write (OnWriteBodyContents) implementation Read-Implementierung (OnGetReaderAtBodyContents)Read (OnGetReaderAtBodyContents) Implementation
Ausgehend, erstellt von nicht per Streaming übertragenem ProgrammiermodellOutgoing, created from nonstreamed programming model Die zum Schreiben der Nachricht benötigten Daten (z.&#160;B. ein Objekt und die zum Serialisieren benötigte DataContractSerializer -Instanz)The data needed to write the message (for example, an object and the DataContractSerializer instance needed to serialize it) Eine benutzerdefinierte Logik zum Schreiben der Nachricht basierend auf den gespeicherten Daten (z.&#160;.B Aufruf von WriteObject am DataContractSerializer , falls dies das verwendete Serialisierungsprogramm ist)Custom logic to write out the message based on the stored data (for example, call WriteObject on the DataContractSerializer if that is the serializer in use) Aufrufen von OnWriteBodyContents, Puffern der Ergebnisse, Ausgeben eines XML-Lesers über den PufferCall OnWriteBodyContents, buffer the results, return an XML reader over the buffer
Ausgehend, erstellt von per Streaming übertragenem ProgrammiermodellOutgoing, created from streamed programming model Der Stream mit den zu schreibenden DatenThe Stream with the data to be written Schreiben von Daten vom gespeicherten Stream mit dem IStreamProvider -Mechanismus Write out data from the stored stream using the IStreamProvider mechanism Aufrufen von OnWriteBodyContents, Puffern der Ergebnisse, Ausgeben eines XML-Lesers über den PufferCall OnWriteBodyContents, buffer the results, return an XML reader over the buffer
Eingehend von StreamingkanalstapelIncoming from streaming channel stack Ein Stream -Objekt, das die Daten darstellt, die über das Netzwerk mit einem darauf angewendeten XmlReader eingehenA Stream object that represents the data coming in over the network with an XmlReader over it Ausschreiben des Inhalts aus dem gespeicherten XmlReader mit WriteNodeWrite out the contents from the stored XmlReader using WriteNode Gibt den gespeicherten XmlReaderzurückReturns the stored XmlReader
Eingehend von nicht per Streaming übertragenem KanalstapelIncoming from nonstreaming channel stack Ein Puffer, der Textdaten enthält, mit einem darauf angewendeten XmlReaderA buffer that contains body data with an XmlReader over it Schreibt den Inhalt des gespeicherten XmlReader mit WriteNodeausWrites out the contents from the stored XmlReader using WriteNode Gibt die gespeicherte Sprache zurückReturns the stored lang

*Diese Elemente werden nicht direkt im implementiert Message Unterklassen, sondern in Unterklassen der der BodyWriter Klasse.* These items are not implemented directly in Message subclasses, but in subclasses of the BodyWriter class. Weitere Informationen zum BodyWriterfinden Sie unter Using the Message Class.For more information about the BodyWriter, see Using the Message Class.

NachrichtenheaderMessage Headers

Eine Nachricht enthält möglicherweise Header.A message may contain headers. Ein Header besteht logisch aus einem XML-Infoset, der einem Namen, einem Namespace und einigen anderen Eigenschaften zugeordnet ist.A header logically consists of an XML Infoset that is associated with a name, a namespace, and a few other properties. Auf Nachrichtenheader wird mit der Headers -Eigenschaft auf Messagezugegriffen.Message headers are accessed using the Headers property on Message. Jeder Header wird durch eine MessageHeader -Klasse dargestellt.Each header is represented by a MessageHeader class. In der Regel sind Nachrichtenheader SOAP-Nachrichtenheadern zugeordnet, wenn ein Kanalstapel verwendet wird, der für SOAP-Nachrichten konfiguriert ist.Normally, message headers are mapped to SOAP message headers when using a channel stack configured to work with SOAP messages.

Das Einfügen von Informationen in einen Nachrichtenheader und das Extrahieren von Daten daraus ähnelt der Verwendung des Nachrichtentexts.Putting information into a message header and extracting information from it is similar to using the message body. Der Prozess wird ein wenig vereinfacht, da das Streaming nicht unterstützt wird.The process is somewhat simplified because streaming is not supported. Es ist möglich, auf den Inhalt desselben Headers mehr als einmal zuzugreifen. Auf die Header kann auch in willkürlicher Reihenfolge zugegriffen werden. Die Header werden dadurch gezwungen, immer gepuffert zu sein.It is possible to access the contents of the same header more than once, and headers can be accessed in arbitrary order, forcing headers to always be buffered. Es gibt keinen Mechanismus für allgemeine Zwecke, um einen XML-Lesers über einen Header laufen zu lassen. Es ist jedoch eine MessageHeader -Unterklasse in WCFWCF verfügbar, die einen lesbaren Header mit einer solchen Funktion darstellt.There is no general-purpose mechanism available to get an XML reader over a header, but there is a MessageHeader subclass internal to WCFWCF that represents a readable header with such a capability. Diese Art von MessageHeader wird vom Kanalstapel erstellt, wenn eine Nachricht mit benutzerdefinierten Anwendungsheadern eingeht.This type of MessageHeader is created by the channel stack when a message with custom application headers comes in. So kann das Dienstframework ein Deserialisierungsmodul, z. B. den DataContractSerializer, zum Interpretieren dieser Header verwenden.This enables the service framework to use a deserialization engine, such as the DataContractSerializer, to interpret these headers.

Weitere Informationen finden Sie unterFor more information, see Using the Message Class. Using the Message Class.

NachrichteneigenschaftenMessage Properties

Eine Nachricht kann Eigenschaften enthalten.A message may contain properties. Eine Eigenschaft ist ein beliebiges .NET Framework.NET Framework -Objekt, das einem Zeichenfolgennamen zugeordnet ist.A property is any .NET Framework.NET Framework object that is associated with a string name. Der Zugriff erfolgt über die Properties -Eigenschaft von Message.Properties are accessed through the Properties property on Message.

Im Gegensatz zum Nachrichtentext und den Nachrichtenheadern (die in der Regel dem SOAP-Text und den SOAP-Headern zugeordnet sind) werden Nachrichteneigenschaften in der Regel nicht zusammen mit den Nachrichten gesendet oder empfangen.Unlike the message body and message headers (which normally map to the SOAP body and SOAP headers, respectively), message properties are normally not sent or received along with the messages. Nachrichteneigenschaften existieren hauptsächlich als Kommunikationsmechanismus zum Übergeben von Daten über die Nachricht zwischen den verschiedenen Kanälen im Kanalstapel und zwischen dem Kanalstapel und dem Dienstmodell.Message properties exist primarily as a communication mechanism to pass data about the message between the various channels in the channel stack, and between the channel stack and the service model.

So kann der als Bestandteil von WCFWCF enthaltene HTTP-Transportkanal verschiedene HTTP-Statuscodes, wie "404 (nicht gefunden)" und "500 (interner Serverfehler)", generieren, wenn Antworten an Clients gesendet werden.For example, the HTTP transport channel included as part of WCFWCF is capable of producing various HTTP status codes, such as "404 (Not Found)" and "500 (Internal Server Error)," when it sends replies to clients. Vor dem Senden einer Antwortnachricht wird geprüft, ob die Properties von der Message enthalten eine Eigenschaft mit dem Namen "HttpResponse", die ein Objekt des Typs enthält HttpResponseMessageProperty.Before sending a reply message, it checks to see whether the Properties of the Message contain a property called "httpResponse" that contains an object of type HttpResponseMessageProperty. Wird eine solche Eigenschaft gefunden, wird die StatusCode -Eigenschaft geprüft und dieser Statuscode verwendet.If such a property is found, it will look at the StatusCode property and use that status code. Andernfalls wird der Standardcode "200 (OK)" verwendet.If it is not found, the default "200 (OK)" code is used.

Weitere Informationen finden Sie unterFor more information, see Using the Message Class. Using the Message Class.

Die Nachricht als GanzesThe Message as a Whole

Bis jetzt wurden Methoden für den Zugriff auf die verschiedenen Bestandteile der Nachricht isoliert erläutert.So far, we have discussed methods for accessing the various parts of the message in isolation. Die Message -Klasse stellt jedoch auch Methoden bereit, die mit der Nachricht als Ganzes ausgeführt werden.However, the Message class also provides methods to work with the entire message as a whole. Die folgende WriteMessage -Methode schreibt z.&#160;B. die gesamte Nachricht in einen XML-Writer.For example, the WriteMessage method writes out the entire message to an XML writer.

Damit dies möglich ist, muss zwischen der gesamten Message -Instanz und einem XML-Infoset eine Zuordnung definiert werden.For this to be possible, a mapping must be defined between the entire Message instance and an XML Infoset. Eine solche Zuordnung ist tatsächlich vorhanden: WCFWCF verwendet den SOAP-Standard, um diese Zuordnung zu definieren.Such a mapping, in fact, exists: WCFWCF uses the SOAP standard to define this mapping. Wenn eine Message -Instanz als XML-Infoset geschrieben wird, ist der daraus resultierende Infoset der gültige SOAP-Umschlag, der die Nachricht enthält.When a Message instance is written out as an XML Infoset, the resulting Infoset is the valid SOAP envelope that contains the message. So würde WriteMessage normalerweise die folgenden Schritte ausführen:Thus, WriteMessage would normally perform the following steps:

  1. Schreiben des öffnenden SOAP-Umschlagelementtags.Write the SOAP envelope element opening tag.

  2. Schreiben des öffnenden SOAP-Headerelementtags, Schreiben aller Header und Schließen des Headerelements.Write the SOAP header element opening tag, write out all of the headers, and close the header element.

  3. Schreiben des öffnenden SOAP-Textkörperelementtags.Write the SOAP body element opening tag.

  4. Aufrufen von WriteBodyContents oder einer entsprechenden Methode zum Schreiben des Texts.Call WriteBodyContents or an equivalent method to write out the body.

  5. Schließen der Text- und Umschlagelemente.Close the body and envelope elements.

Die vorhergehenden Schritte sind eng an den SOAP-Standard gebunden.The preceding steps are closely tied to the SOAP standard. Dies wird durch die Tatsache komplizierter, dass mehrere SOAP-Versionen vorhanden sind. So ist es z. B. möglich, das SOAP-Umschlagelement richtig zu schreiben, ohne die verwendete SOAP-Version zu kennen.This is complicated by the fact that multiple versions of SOAP exist, for example, it is impossible to write out the SOAP envelope element correctly without knowing the SOAP version in use. Auch in einigen Fällen ist es möglicherweise wünschenswert, diese komplexe SOAP-spezifische Zuordnung völlig auszuschalten.Also, in some cases, it may be desirable to turn off this complex SOAP-specific mapping completely.

Für diese Zwecke wird eine Version -Eigenschaft für Messagebereitgestellt.For these purposes, a Version property is provided on Message. Sie kann auf die SOAP-Version festgelegt werden, die beim Schreiben der Nachricht verwendet wird, oder sie kann auf None festgelegt werden, um SOAP-spezifische Zuordnungen zu verhindern.It can be set to the SOAP version to use when writing out the message, or it can be set to None to prevent any SOAP-specific mappings. Falls die Version -Eigenschaft auf Nonefestgelegt ist, funktionieren Methoden, die mit der gesamten Nachricht arbeiten, so, als ob die Nachricht lediglich aus dem Textkörper besteht. So würde z.&#160;B. WriteMessage einfach WriteBodyContents aufrufen, und die oben beschriebenen Schritte werden nicht ausgeführt.If the Version property is set to None, methods that work with the entire message act as if the message consisted of its body only, for example, WriteMessage would simply call WriteBodyContents instead of performing the multiple steps listed above. Es wird erwartet, dass Version in eingehenden Nachrichten automatisch erkannt und ordnungsgemäß festgelegt wird.It is expected that on incoming messages, Version will be auto-detected and set correctly.

Der KanalstapelThe Channel Stack

ChannelsChannels

Wie zuvor bereits beschrieben, ist der Kanalstapel für die Umwandlung von ausgehenden Message -Instanzen in eine Aktion (wie Senden von Paketen über das Netzwerk) oder Umwandeln einer Aktion (wie Empfangen von Netzwerkpakten) in eingehende Message -Instanzen verantwortlich.As stated before, the channel stack is responsible for converting outgoing Message instances into some action (such as sending packets over the network), or converting some action (such as receiving network packets) into incoming Message instances.

Der Kanalstapel besteht aus einem oder aus mehreren Kanälen, die in einer Sequenz angeordnet sind.The channel stack is composed of one or more channels ordered in a sequence. Eine ausgehende Message -Instanz wird an den ersten Kanal im Stapel (auch als oberster Kanalbezeichnet) übergeben, der sie wiederum an den nächsten Kanal im Stapel übergibt usw.An outgoing Message instance is passed to the first channel in the stack (also called the topmost channel), which passes it to the next channel down in stack, and so on. Die Nachricht endet im letzten Kanal, der als Transportkanalbezeichnet wird.The message terminates in the last channel, which is called the transport channel. Eingehende Nachrichten stammen aus dem Transportkanal und werden von Kanal zu Kanal nach oben im Stapel übergeben.Incoming messages originate in the transport channel and are passed from channel to channel up the stack. Vom obersten Kanal wird die Nachricht normalerweise in das Dienstframework übergeben.From the topmost channel, the message is usually passed into the service framework. Dies ist das Muster für Anwendungsnachrichten, das in der Regel verwendet wird. Einige Kanäle funktionieren eventuell anders. Sie senden z. B. eigene Infrastrukturnachrichten, ohne eine Nachricht von einem oben beschriebenen Kanal zu erhalten.While this is the usual pattern for application messages, some channels may work slightly differently, for example, they may send their own infrastructure messages without being passed a message from a channel above.

Die Kanäle wirken möglicherweise auf verschiedene Weise auf die Nachricht, die durch den Stapel geleitet wird.Channels may operate on the message in various ways as it passes through the stack. Der am häufigsten verwendete Vorgang besteht im Hinzufügen eines Headers zu einer ausgehenden Nachricht sowie im Lesen der Header einer eingehenden Nachricht.The most common operation is adding a header to an outgoing message and reading headers on an incoming message. So kann ein Kanal z. B. die digitale Signatur einer Nachricht berechnen und sie als Header hinzufügen.For example, a channel may compute the digital signature of a message and add it as a header. Ein Kanal kann diesen digitalen Signaturheader in eingehenden Nachrichten auch prüfen und Nachrichten, die keine gültige Signatur enthalten, auf ihrem Weg durch den Kanalstapel blockieren.A channel may also inspect this digital signature header on incoming messages and block messages that do not have a valid signature from making their way up the channel stack. Kanäle legen auch häufig Nachrichteneigenschaften fest oder prüfen diese.Channels also often set or inspect message properties. Der Nachrichtentext wird in der Regel nicht geändert, obwohl dies zulässig ist. So kann z.&#160;B. der WCFWCF -Sicherheitskanal den Nachrichtentext verschlüsseln.The message body is usually not modified, although this is allowed, for example, the WCFWCF security channel can encrypt the message body.

Transportkanäle und NachrichtenencoderTransport Channels and Message Encoders

Der Kanal, der sich im Stapel ganz unten befindet, ist für die Übertragung einer ausgehenden Message-Nachricht, die von anderen Kanälen geändert wurde, in eine Aktion verantwortlich.The bottommost channel in the stack is responsible for actually transforming an outgoing Message, as modified by other channels, into some action. Auf Empfängerseite ist dies der Kanal, der eine Aktion in eine Message umwandelt, die von anderen Kanälen verarbeitet wird.On the receive side, this is the channel that converts some action into a Message that other channels process.

Wie zuvor bereits erläutert kann es sich um verschiedene Aktionen handeln: Senden oder Empfangen von Netzwerkpaketen über verschiedene Protokolle, Lesen und Schreiben der Nachricht in einer Datenbank oder Ablegen oder Abrufen der Nachricht aus einer Warteschlange von Message Queuing, um nur einige Beispiele zu nennen.As stated previously, the actions may be varied: sending or receiving network packets over various protocols, reading or writing the message in a database, or queuing or dequeuing the message in a Message Queuing queue, to provide but a few examples. Alle diese Aktionen haben eines gemeinsam: Sie setzen eine Umwandlung zwischen der WCFWCFMessage und einer tatsächlichen Gruppe von Bytes voraus, die gesendet, empfangen, gelesen, geschrieben, in Warteschlangen gestellt oder aus Warteschlangen abgerufen werden können.All these actions have one thing in common: they require a transformation between the WCFWCFMessage instance and an actual group of bytes that can be sent, received, read, written, queued, or dequeued. Der Vorgang des Umwandelns einer Message in eine Gruppe von Bytes wird als Codierenbezeichnet, und der umgekehrte Vorgang des Erstellens einer Message aus einer Gruppe von Bytes wird als Decodierenbezeichnet.The process of converting a Message into a group of bytes is called encoding, and the reverse process of creating a Message from a group of bytes is called decoding.

Die meisten Transportkanäle verwenden Komponenten, die als Nachrichtenencoder bezeichnet werden, um die Codierung und Decodierung durchzuführen.Most transport channels use components called message encoders to accomplish the encoding and decoding work. Ein Nachrichtenencoder ist eine Unterklasse der MessageEncoder -Klasse.A message encoder is a subclass of the MessageEncoder class. MessageEncoder umfasst verschiedene ReadMessage - und WriteMessage -Methodenüberladungen, um eine Konvertierung zwischen Message und Gruppen von Bytes durchzuführen.MessageEncoder includes various ReadMessage and WriteMessage method overloads to convert between Message and groups of bytes.

Auf der Absenderseite übergibt ein Puffertransportkanal das Message -Objekt, das es von einem Kanal darüber erhalten hat, an WriteMessage.On the sending side, a buffering transport channel passes the Message object that it received from a channel above it to WriteMessage. Es erhält ein Bytearray zurück, das zum Durchführen der Aktion (wie Packen dieser Bytes als gültige TCP-Pakete und Senden an das richtige Ziel) verwendet wird.It gets back an array of bytes, which it then uses to perform its action (such as packaging these bytes as valid TCP packets and sending them to the correct destination). Ein Streaming-Transportkanal erstellt zunächst einen Stream (z.&#160;B. für die ausgehende TCP-Verbindung) und übergibt dann sowohl den Stream als auch die Message an die entsprechende WriteMessage -Überladung, welche die Nachricht schreibt.A streaming transport channel first creates a Stream (for example, over the outgoing TCP connection), and then passes both the Stream and the Message it needs to send to the appropriate WriteMessage overload, which writes out the message.

Auf der Empfängerseite extrahiert ein Puffertransportkanal eingehende Bytes (z.&#160;B. aus eingehenden TCP-Paketen) in ein Array und ruft ReadMessage auf, um ein Message -Objekt abzurufen, das im Kanalstapel weiter nach oben übergeben werden kann.On the receiving side, a buffering transport channel extracts incoming bytes (for example, from incoming TCP packets) into an array and calls ReadMessage to get a Message object that it can pass further up the channel stack. Ein Streamingtransportkanal erstellt ein Stream -Objekt (z.&#160;B. einen Netzwerkstream über die eingehende TCP-Verbindung) und übergibt dieses an ReadMessage , um ein Message -Objekt zu erhalten.A streaming transport channel creates a Stream object (for example, a network stream over the incoming TCP connection) and passes that to ReadMessage to get back a Message object.

Die Trennung zwischen den Transportkanälen und dem Nachrichtenencoder ist nicht erforderlich. Es ist möglich, einen Transportkanal zu schreiben, der keinen Nachrichtenencoder verwendet.The separation between the transport channels and the message encoder is not mandatory; it is possible to write a transport channel that does not use a message encoder. Der Vorteil dieser Trennung liegt jedoch in der einfachen Zusammensetzung.However, the advantage of this separation is ease of composition. Solange ein Transportkanal nur den Basis- MessageEncoderverwendet, funktioniert er mit jedem beliebigen WCFWCF - oder Drittanbieter-Nachrichtenencoder.As long as a transport channel uses only the base MessageEncoder, it can work with any WCFWCF or third-party message encoder. Ebenso kann der gleiche Encoder normalerweise in jedem Transportkanal verwendet werden.Likewise, the same encoder can normally be used in any transport channel.

NachrichtenencodervorgangMessage Encoder Operation

Um den typischen Vorgang eines Encoders zu beschreiben, ist es nützlich, die folgenden vier Fälle zu betrachten.To describe the typical operation of an encoder, it is useful to consider the following four cases.

VorgangOperation KommentarComment
Codierung, gepuffertEncoding, Buffered Im gepufferten Modus erstellt der Encoder in der Regel einen Puffer in verschiedenen Größen und dann einen XML-Writer dafür.In buffered mode, the encoder normally creates a variable-size buffer and then creates an XML writer over it. Er ruft dann WriteMessage(XmlWriter) für die codierte Nachricht auf. Dadurch werden die Header ausgeschrieben und anschließend der Textkörper mithilfe von WriteBodyContents(XmlDictionaryWriter), wie im folgenden Abschnitt über Message in diesem Thema beschrieben.It then calls WriteMessage(XmlWriter) on the message being encoded, which writes out the headers and then the body using WriteBodyContents(XmlDictionaryWriter), as explained in the preceding section about Message in this topic. Der Inhalt des Puffers (dargestellt als Bytearray) wird dann für die Verwendung vom Transportkanal zurückgegeben.The contents of the buffer (represented as an array of bytes) are then returned for the transport channel to use.
Codierung, per Streaming übertragenEncoding, Streamed Im Streammodus ist der Vorgang ähnlich wie der oben beschriebene, aber einfacher.In streamed mode, the operation is similar to the above, but simpler. Es ist kein Puffer erforderlich.There is no need for a buffer. Für den Stream wird in der Regel ein XML-Writer erstellt und WriteMessage(XmlWriter) für Message aufgerufen, um für diesen Writer zu schreiben.An XML writer is normally created over the stream and WriteMessage(XmlWriter) is called on the Message to write it out to this writer.
Decodierung, gepuffertDecoding, Buffered Wenn Sie im Puffermodus decodieren, wird eine besondere Message -Unterklasse erstellt, die die gepufferten Daten enthält.When decoding in buffered mode, a special Message subclass that contains the buffered data is normally created. Die Header der Nachricht werden gelesen, und ein XML-Leser, der sich im Nachrichtentext befindet, wird erstellt.The headers of the message are read, and an XML reader positioned on the message body is created. Dies ist der Leser, der mit GetReaderAtBodyContents()zurückgegeben wird.This is the reader that will be returned with GetReaderAtBodyContents().
Decodierung, per Streaming übertragenDecoding, Streamed Wenn Sie im Streammodus decodieren, wird in der Regel eine besondere Nachrichtenunterklasse erstellt.When decoding in streamed mode, a special Message subclass is normally created. Der Stream wird gerade so weit bewegt, dass alle Header gelesen werden können und er im Nachrichtentext positioniert wird.The stream is advanced just enough to read all the headers and position it on the message body. Ein XML-Leser wird dann über dem Datenstrom erstellt.An XML reader is then created over the stream. Dies ist der Leser, der mit GetReaderAtBodyContents()zurückgegeben wird.This is the reader that will be returned with GetReaderAtBodyContents().

Encoder können auch andere Funktionen ausführen.Encoders can perform other functions as well. Zum Beispiel können die Encoder XML-Leser und -Writer zusammenlegen.For example, the encoders can pool XML readers and writers. Es ist teuer, jedes Mal einen neuen XML-Leser oder -Writer zu erstellen, wenn einer benötigt wird.It is expensive to create a new XML reader or writer every time one is needed. Deshalb verwalten Encoder normalerweise einen Pool von Lesern und einen Pool von Writern in konfigurierbaren Größen.Therefore, encoders normally maintain a pool of readers and a pool of writers of configurable size. In den Beschreibungen von Codierungsvorgängen zuvor bedeutet die Formulierung "einen XML Leser/Schreiber erstellen" werden verwendet, die es normalerweise "einen aus dem Pool nehmen, oder erstellen Sie eine Option, wenn eine nicht verfügbar ist."In the descriptions of encoder operation described previously, whenever the phrase "create an XML reader/writer" is used, it normally means "take one from the pool, or create one if one is not available." Der Encoder (und die Message -Unterklassen, die er beim Decodieren erstellt) enthält Logik zum Zurückgeben von Lesern und Schreibern an den Pool, wenn sie nicht mehr benötigt werden (z. B. wenn die Message geschlossen wird).The encoder (and the Message subclasses it creates while decoding) contain logic to return readers and writers to the pools once they are no longer needed (for example, when the Message is closed).

WCFWCF stellt drei Nachrichtenencoder zur Verfügung, obwohl es möglich ist, zusätzliche benutzerdefinierte Typen zu erstellen. provides three message encoders, although it is possible to create additional custom types. Die angegebenen Typen sind Text, Binärdatei und MTOM (Message Transmission Optimization Mechanism, Nachrichtenübertragungs-Optimierungsmechanismus).The supplied types are Text, Binary, and Message Transmission Optimization Mechanism (MTOM). Diese werden detailliert unter Choosing a Message Encoderbeschrieben.These are described in detail in Choosing a Message Encoder.

Die IStreamProvider-SchnittstelleThe IStreamProvider Interface

Wenn eine ausgehende Nachricht, die einen in einem Stream befindlichen Hauptteil enthält, in einen XML-Writer geschrieben wird, verwendet Message eine Aufrufsequenz, die der folgenden Sequenz in ihrer OnWriteBodyContents(XmlDictionaryWriter) -Implementierung ähnlich ist:When writing an outgoing message that contains a streamed body to an XML writer, the Message uses a sequence of calls similar to the following in its OnWriteBodyContents(XmlDictionaryWriter) implementation:

  • Schreiben Sie alle notwendigen Informationen, die dem Stream vorausgehen (z. B. das öffnende XML-Tag).Write any necessary information preceding the stream (for example, the opening XML tag).

  • Schreiben Sie den Stream.Write the stream.

  • Schreiben Sie alle Informationen, die nach dem Stream folgen (z. B. das schließende XML-Tag).Write any information following the stream (for example, the closing XML tag).

Dies funktioniert gut bei Codierungen, die der Text-XML-Codierung ähnlich sind.This works well with encodings that are similar to the textual XML encoding. Es gibt jedoch einige Codierungen, bei denen XML-Infosetinformationen (z. B. Tags für beginnende und endende XML-Elemente) nicht zusammen mit den in den Elementen enthaltenen Daten platziert werden.However, some encodings do not place XML Infoset information (for example, tags for starting and ending XML elements) together with the data contained within elements. Zum Beispiel wird bei der MTOM-Codierung die Nachricht in mehrere Teile aufgeteilt.For example, in the MTOM encoding, the message is split into multiple parts. Ein Teil enthält den XML-Infoset, der in Bezug auf tatsächlichen Elementinhalt Verweise auf andere Teile enthalten kann.One part contains the XML Infoset, which may contain references to other parts for actual element contents. Da der XML-Infoset für gewöhnlich kleiner ist als der im Stream befindliche Inhalt, bietet es sich an, den Infoset zu puffern, ihn auszuschreiben und dann den Inhalt gestreamt zu schreiben.The XML Infoset is normally small compared to the streamed contents, so it makes sense to buffer the Infoset, write it out, and then write the contents in a streamed way. Dies bedeutet, dass zu dem Zeitpunkt, zu dem das Tag für das schließende Element geschrieben wird, der Stream noch nicht ausgeschrieben sein sollte.This means that by the time the closing element tag is written, the stream should not have been written out yet.

Zu diesem Zweck wird die IStreamProvider -Schnittstelle verwendet.For this purpose, the IStreamProvider interface is used. Die Schnittstelle verfügt über eine GetStream() -Methode, die den zu schreibenden Stream zurückgibt.The interface has a GetStream() method that returns the stream to be written. Die richtige Vorgehensweise, um einen in einem Stream befindlichen Nachrichtentext in OnWriteBodyContents(XmlDictionaryWriter) auszuschreiben, lautet wie folgt:The correct way to write out a streamed message body in OnWriteBodyContents(XmlDictionaryWriter) is as follows:

  1. Schreiben Sie alle notwendigen Informationen, die dem Stream vorausgehen (z. B. das öffnende XML-Tag).Write any necessary information preceding the stream (for example, the opening XML tag).

  2. Rufen Sie die WriteValue -Überladung in XmlDictionaryWriter auf, die IStreamProvidermit einer IStreamProvider -Implementierung verwendet, die den zu schreibenden Stream zurückgibt.Call the WriteValue overload on the XmlDictionaryWriter that takes an IStreamProvider, with an IStreamProvider implementation that returns the stream to be written.

  3. Schreiben Sie alle Informationen, die nach dem Stream folgen (z. B. das schließende XML-Tag).Write any information following the stream (for example, the closing XML tag).

Auf diese Weise kann der XML-Writer bestimmen, wann GetStream() aufgerufen wird und die im Stream befindlichen Daten ausgeschrieben werden.With this approach, the XML writer has a choice of when to call GetStream() and write out the streamed data. So rufen die Text-XML-Writer und die binären XML-Writer die Daten zum Beispiel direkt auf und schreiben den im Stream befindlichen Inhalt zwischen die Start- und Endtags.For example, the textual and binary XML writers will call it immediately and write out the streamed contents in-between the start and end tags. Der MTOM-Writer ruft GetStream() möglicherweise erst dann auf, wenn er zum Schreiben des entsprechenden Nachrichtenteils bereit ist.The MTOM writer may decide to call GetStream() later, when it is ready to write the appropriate part of the message.

Darstellen von Daten im DienstframeworkRepresenting Data in the Service Framework

Wie im Abschnitt "Basisarchitektur" in diesem Thema bereits beschrieben, ist das Dienstframework der Teil von WCFWCF , der u.&#160;a. für die Konvertierung zwischen einem benutzerfreundlichen Programmiermodell für Nachrichtendaten und den tatsächlichen Message -Instanzen verantwortlich ist.As stated in the "Basic Architecture" section of this topic, the service framework is the part of WCFWCF that, among other things, is responsible for converting between a user-friendly programming model for message data and actual Message instances. In der Regel wird ein Nachrichtenaustausch im Dienstframework als eine .NET Framework.NET Framework -Methode dargestellt, die mit dem Attribut OperationContractAttribute gekennzeichnet ist.Normally, a message exchange is represented in the service framework as a .NET Framework.NET Framework method marked with the OperationContractAttribute attribute. Die Methode kann einige Parameter ausführen und einen Rückgabewert oder out-Parameter (oder beides) zurückgeben.The method can take in some parameters and can return a return value or out parameters (or both). Auf der Dienstseite stellen die Eingabeparameter die eingehende Nachricht dar. Der Rückgabewert und die out-Parameter stellen die ausgehende Nachricht dar.On the service side, the input parameters represent the incoming message, and the return value and out parameters represent the outgoing message. Auf der Clientseite gilt das Gegenteil.On the client side, the reverse is true. Das Programmiermodell zum Beschreiben von Nachrichten mithilfe von Parametern und Rückgabewert wird ausführlich unter Specifying Data Transfer in Service Contractsbeschrieben.The programming model for describing messages using parameters and the return value is described in detail in Specifying Data Transfer in Service Contracts. Der folgende Abschnitt enthält jedoch eine kurze Übersicht.However, this section will provide a brief overview.

ProgrammiermodelleProgramming Models

Das WCFWCF-Dienstframework unterstützt fünf verschiedene Programmiermodelle zum Beschreiben von Nachrichten:The WCFWCF service framework supports five different programming models for describing messages:

1. Die leere Nachricht1. The Empty Message

Dies ist der einfachste Fall.This is the simplest case. Um eine leere eingehende Nachricht zu beschreiben, verwenden Sie keine Eingabeparameter.To describe an empty incoming message, do not use any input parameters.

[OperationContract]
int GetCurrentTemperature();
<OperationContract()> Function GetCurrentTemperature() As Integer

Um eine leere ausgehende Nachricht zu beschreiben, verwenden Sie einen void-Rückgabewert:To describe an empty outgoing message, use a void return value and do not use any out parameters:

[OperationContract]
void SetDesiredTemperature(int t);
<OperationContract()> Sub SetDesiredTemperature(ByVal t As Integer)

Beachten Sie, dass sich dies von einem unidirektionalen Vorgangsvertrag unterscheidet:Note that this is different from a one-way operation contract:

[OperationContract(IsOneWay = true)]
void SetLightbulb(bool isOn);
<OperationContract(IsOneWay:=True)> Sub SetLightbulb(ByVal isOn As Boolean)

Im SetDesiredTemperature -Beispiel wird ein bidirektionales Nachrichtenaustauschmuster beschrieben.In the SetDesiredTemperature example, a two-way message exchange pattern is described. Eine Nachricht wird vom Vorgang zurückgegeben, ist jedoch leer.A message is returned from the operation, but it is empty. Es ist möglich, einen Fehler vom Vorgang zurückzugeben.It is possible to return a fault from the operation. Im Beispiel "Set Lightbulb" ist das Nachrichtenaustauschmuster unidirektional. Es ist also keine ausgehende Nachricht vorhanden, die beschrieben werden müsste.In the "Set Lightbulb" example, the message exchange pattern is one-way, so there is no outgoing message to describe. Der Dienst kann dem Client in diesem Fall keinen Status mitteilen.The service cannot communicate any status back to the client in this case.

2. Direktes Verwenden der Nachrichtenklasse2. Using the Message Class Directly

Es ist möglich, die Message -Klasse (oder eine ihrer Unterklassen) direkt in einem Vertrag für einen Vorgang zu verwenden.It is possible to use the Message class (or one of its subclasses) directly in an operation contract. In diesem Fall übergibt das Dienstframework Message einfach an den Kanalstapel und umgekehrt, ohne weitere Verarbeitung.In this case, the service framework just passes the Message from the operation to the channel stack and vice versa, with no further processing.

Es gibt zwei Hauptanwendungsfälle für das direkte Verwenden von Message .There are two main use cases for using Message directly. Sie können es für erweiterte Szenarien verwenden, wenn keines der anderen Programmiermodelle ausreichende Flexibilität zum Beschreiben Ihrer Nachricht bietet.You can use this for advanced scenarios, when none of the other programming models gives you enough flexibility to describe your message. So möchten Sie z. B. eventuell Dateien auf Festplatte zum Beschreiben einer Nachricht verwenden, wobei die Dateieigenschaften zu Nachrichtenheadern werden und der Dateiinhalt zum Nachrichtentext wird.For example, you might want to use files on disk to describe a message, with the file’s properties becoming message headers and the file’s contents becoming the message body. Sie können dann Folgendes erstellen.You can then create something similar to the following.

public class FileMessage : Message
// Code not shown.
Public Class FileMessage
    Inherits Message
    ' Code not shown.

Der zweite häufige Anwendungsfall für Message in einem Vorgangsvertrag tritt ein, wenn ein Dienst den Inhalt einer bestimmten Nachricht ignoriert und die Nachricht wie eine Blackbox behandelt.The second common use for Message in an operation contract is when a service does not care about the particular message contents and acts on the message as on a black box. Zum Beispiel könnten Sie über einen Dienst verfügen, der Nachrichten an mehrere andere Empfänger weiterleitet.For example, you might have a service that forwards messages to multiple other recipients. Der Vertrag kann wie folgt geschrieben werden.The contract can be written as follows.

[OperationContract]
public FileMessage GetFile()
{
    //code omitted�
    FileMessage fm = new FileMessage("myFile.xml");
    return fm;

}
<OperationContract()> Public Function GetFile() As FileMessage
    'code omitted�
    Dim fm As New FileMessage("myFile.xml")
    Return fm
End Function

Die Aktion = "" Zeile effektiv die nachrichtenverteilung wird deaktiviert, und stellt sicher, dass alle Nachrichten, um gesendet die IForwardingService Vertrag stellen die Möglichkeit, die ForwardMessage Vorgang.The Action="" line effectively turns off message dispatching and ensures that all messages sent to the IForwardingService contract make their way to the ForwardMessage operation. (Normalerweise würde der Verteiler untersuchen Sie die Nachricht "Action"-Header, um zu bestimmen, welcher Vorgang Zweck.(Normally, the dispatcher would examine the message’s "Action" header to determine which operation it is intended for. Action = "*" bedeutet "alle möglichen Werte des Action-Headers".) Die Kombination aus Action = "*" und die Nutzung von Nachrichten, wie ein Parameter als "universeller Vertrag" bezeichnet wird, da alle möglichen Nachrichten empfangen kann.Action="*" means "all possible values of the Action header".) The combination of Action="*" and using Message as a parameter is known as the "universal contract" because it is able to receive all possible messages. Um alle möglichen Nachrichten senden zu können, verwenden Sie Message als Rückgabewert, und legen Sie ReplyAction zu "*".To be able to send all possible messages, use Message as the return value and set ReplyAction to "*". Auf diese Weise wird verhindert, dass das Dienstframework einen eigenen Action-Header hinzufügt. So können Sie diesen Header mit dem zurückgegebenen Message -Objekt steuern.This will prevent the service framework from adding its own Action header, enabling you to control this header using the Message object you return.

3. Nachrichtenverträge3. Message Contracts

WCFWCF stellt ein deklaratives Programmiermodell zum Beschreiben von Nachrichten bereit, die so genannten Nachrichtenverträge. provides a declarative programming model for describing messages, called message contracts. Dieses Modell wird in Using Message Contractsausführlich beschrieben.This model is described in detail in Using Message Contracts. Die gesamte Nachricht wird als einzelner .NET Framework.NET Framework -Typ dargestellt, der Attribute wie MessageBodyMemberAttribute und MessageHeaderAttribute verwendet, um zu beschreiben, welche Teile der Nachrichtenvertragsklasse welchem Teil der Nachricht zugeordnet werden sollen.Essentially, the entire message is represented by a single .NET Framework.NET Framework type that uses attributes like the MessageBodyMemberAttribute and MessageHeaderAttribute to describe which parts of the message contract class should map to which part of the message.

Nachrichtenverträge bieten einen hohen Steuerungsgrad hinsichtlich der resultierenden Message -Instanzen (obwohl offensichtlich nicht so viel Steuerung wie bei der direkten Verwendung der Message -Klasse).Message contracts provide a lot of control over the resulting Message instances (although obviously not as much control as using the Message class directly). So bestehen Nachrichtentexte häufig aus mehreren Informationskomponenten, von denen jede durch ein XML-Element dargestellt ist.For example, message bodies are often composed of multiple pieces of information, each represented by its own XML element. Diese Elemente können entweder direkt im Textkörper (leerer Modus) vorhanden oder in ein übergeordnetes XML-Element eingeschlossen sein.These elements can either occur directly in the body (bare mode) or can be wrapped in an encompassing XML element. Mit dem Programmiermodell für Nachrichtenverträge können Sie zwischen dem leeren und eingeschlossenen Modus wählen und den Wrappernamen und Namespace steuern.Using the message contract programming model enables you to make the bare-versus-wrapped decision and control the name of the wrapper name and namespace.

Im folgenden Codebeispiel eines Nachrichtenvertrags werden diese Funktionen veranschaulicht.The following code example of a message contract demonstrates these features.

[MessageContract(IsWrapped = true, WrapperName = "Order")]
public class SubmitOrderMessage
{
    [MessageHeader]
    public string customerID;
    [MessageBodyMember]
    public string item;
    [MessageBodyMember]
    public int quantity;
}
<MessageContract(IsWrapped:=True, WrapperName:="Order")> _
Public Class SubmitOrderMessage
    <MessageHeader()> Public customerID As String
    <MessageBodyMember()> Public item As String
    <MessageBodyMember()> Public quantity As Integer
End Class

Für die Serialisierung (mit dem Attribut MessageBodyMemberAttribute, MessageHeaderAttributeoder anderen verwandten Attributen) gekennzeichnete Elemente müssen serialisierbar sein, um an einem Nachrichtenvertrag teilzunehmen.Items marked to be serialized (with the MessageBodyMemberAttribute, MessageHeaderAttribute, or other related attributes) must be serializable to participate in a message contract. Weitere Informationen finden Sie unterFor more information, see dem Abschnitt "Serialisierung" weiter unten in diesem Thema. the "Serialization" section later in this topic.

4. Parameter4. Parameters

Häufig benötigt ein Entwickler, der einen Vorgang beschreiben möchte, der für mehrere Datenpakete gilt, nicht den Steuerungsgrad, den Nachrichtenverträge bieten.Often, a developer who wants to describe an operation that acts on multiple pieces of data does not need the degree of control that message contracts provide. So muss z. B. beim Erstellen von neuen Diensten keine Entscheidung zwischen leer und eingeschlossen getroffen und kein Name für ein Wrapperelement festgelegt werden.For example, when creating new services, one does not usually want to make the bare-versus-wrapped decision and decide on the wrapper element name. Diese Entscheidungen setzen häufig eine tief greifende Kenntnis von Webdiensten und SOAP voraus.Making these decisions often requires deep knowledge of Web services and SOAP.

Das WCFWCF -Dienstframework kann die optimale und interoperable SOAP-Darstellung zum Senden oder Empfangen von mehreren Informationspaketen automatisch auswählen, ohne diese Auswahl dem Benutzer aufzuzwingen.The WCFWCF service framework can automatically pick the best and most interoperable SOAP representation for sending or receiving multiple related pieces of information, without forcing these choices on the user. Dies wird erreicht, indem diese Informationspakete als Parameter oder Rückgabewerte eines Vorgangsvertrags beschrieben werden.This is accomplished by simply describing these pieces of information as parameters or return values of an operation contract. Betrachten Sie z. B. den folgenden Vorgangsvertrag.For example, consider the following operation contract.

[OperationContract]
void SubmitOrder(string customerID, string item, int quantity);
<OperationContract()> _
Sub SubmitOrder( _
    ByVal customerID As String, _
    ByVal item As String, _
    ByVal quantity As Integer)

Das Dienstframework entscheidet automatisch, alle drei Informationsabschnitte (customerID, itemund quantity) in den Nachrichtentext zu integrieren und sie in ein Wrapper-Element mit dem Namen SubmitOrderRequesteinzuschließen.The service framework automatically decides to put all three pieces of information (customerID, item, and quantity) into the message body and wrap them in a wrapper element named SubmitOrderRequest.

Die Beschreibung der Informationen, die als einfache Liste mit Vorgangsvertragsparametern gesendet oder empfangen werden, ist die empfohlene Methode, falls keine besonderen Gründe für einen Wechsel zu dem komplexeren Nachrichtenvertrag oder Message-basierten Programmiermodell vorliegen.Describing the information to be sent or received as a simple list of operation contract parameters is the recommended approach, unless special reasons exist to move to the more-complex message contract or Message-based programming models.

5. Stream5. Stream

Die Verwendung eines Stream oder einer seiner Unterklassen in einem Vorgangsvertrag oder als einzelner Nachrichtentextteil in einem Nachrichtenvertrag kann als separates Programmiermodell im Gegensatz zu den oben beschriebenen betrachtet werden.Using Stream or one of its subclasses in an operation contract or as a sole message body part in a message contract can be considered a separate programming model from the ones described above. Die Verwendung eines Stream auf diese Weise ist die einzige Möglichkeit, zu gewährleisten, dass Ihr Vertrag für ein Streamingmodell verwendet werden kann, fast so, als ob Sie eine eigene Streaming-kompatible Message -Unterklasse schreiben würden.Using Stream in this way is the only way to guarantee that your contract will be usable in a streamed fashion, short of writing your own streaming-compatible Message subclass. Weitere Informationen finden Sie unterFor more information, seeUmfangreiche Daten und Streaming. Large Data and Streaming.

Wenn der Stream oder eine seiner Unterklassen auf diese Art verwendet wird, wird das Serialisierungsprogramm nicht aufgerufen.When Stream or one of its subclasses is used in this way, the serializer is not invoked. Für ausgehende Nachrichten wird eine besondere Message -Streaming-Unterklasse erstellt, und der Stream wird ausgeschrieben, wie im Abschnitt über die IStreamProvider -Schnittstelle beschrieben.For outgoing messages, a special streaming Message subclass is created and the stream is written out as described in the section on the IStreamProvider interface. Für eingehende Nachrichten erstellt das Dienstframework eine Stream-Unterklasse über der eingehenden Nachricht und übergibt sie an den Vorgang.For incoming messages, the service framework creates a Stream subclass over the incoming message and provides it to the operation.

Einschränkungen des ProgrammiermodellsProgramming Model Restrictions

Die oben beschriebenen Programmiermodelle können nicht willkürlich kombiniert werden.The programming models described above cannot be arbitrarily combined. Wenn ein Vorgang beispielsweise einen Nachrichtenvertragstyp akzeptiert, muss der Nachrichtenvertrag der einzige Eingabeparameter sein.For example, if an operation accepts a message contract type, the message contract must be its only input parameter. Darüber hinaus muss der Vorgang dann entweder eine leere Nachricht (ungültiger Rückgabewert) oder einen anderen Nachrichtenvertrag zurückgeben.Furthermore, the operation must then either return an empty message (return type of void) or another message contract. Diese Einschränkungen des Programmiermodells werden in den Themen für jedes einzelne Programmiermodell beschrieben: Using Message Contracts, Using the Message Classund Large Data and Streaming.These programming model restrictions are described in the topics for each specific programming model: Using Message Contracts, Using the Message Class, and Large Data and Streaming.

NachrichtenformatierungsprogrammeMessage Formatters

Die oben beschriebenen Programmiermodelle werden von Plug-In-Komponenten, so genannten Nachrichtenformatierungsprogrammen , in das Dienstframework unterstützt.The programming models described above are supported by plugging in components called message formatters into the service framework. Nachrichtenformatierungsprogramme sind Typen, mit denen die IClientMessageFormatter -Schnittstelle oder IDispatchMessageFormatter -Schnittstelle implementiert wird, oder beide, um sie auf Clients bzw. WCFWCF -Dienstclients zu verwenden.Message formatters are types that implement the IClientMessageFormatter or IDispatchMessageFormatter interface, or both, for use in clients and service WCFWCF clients, respectively.

Nachrichtenformatierungsprogramme werden normalerweise über bestimmte Verhalten implementiert.Message formatters are normally plugged in by behaviors. Zum Beispiel implementiert DataContractSerializerOperationBehavior das Daten-Vertragsnachrichten-Formatierungsprogramm.For example, the DataContractSerializerOperationBehavior plugs in the data contract message formatter. Dies geschieht auf der Dienstseite, indem Formatter auf das richtige Formatierungsprogramm der ApplyDispatchBehavior(OperationDescription, DispatchOperation) -Methode festgelegt wird, oder auf der Clientseite, indem Formatter auf das richtige Formatierungsprogramm der ApplyClientBehavior(OperationDescription, ClientOperation) -Methode festgelegt wird.This is done on the service side by setting Formatter to the correct formatter in the ApplyDispatchBehavior(OperationDescription, DispatchOperation) method, or on the client side by setting Formatter to the correct formatter in the ApplyClientBehavior(OperationDescription, ClientOperation) method.

Die folgenden Tabellen listen die Methoden auf, die ein Nachrichtenformatierungsprogramm möglicherweise implementiert.The following tables lists the methods that a message formatter may implement.

InterfaceInterface MethodeMethod AktionAction
IDispatchMessageFormatter DeserializeRequest(Message, Object[]) Konvertiert eine eingehende Message in VorgangsparameterConverts an incoming Message to operation parameters
IDispatchMessageFormatter SerializeReply(MessageVersion, Object[], Object) Erstellt eine ausgehende Message aus Vorgangsrückgabewert/out-ParameternCreates an outgoing Message from operation return value/out parameters
IClientMessageFormatter SerializeRequest(MessageVersion, Object[]) Erstellt eine ausgehende Message aus VorgangsparameternCreates an outgoing Message from operation parameters
IClientMessageFormatter DeserializeReply(Message, Object[]) Konvertiert eine eingehende Message in einen Rückgabewert/out-ParameterConverts an incoming Message to a return value/out parameters

SerialisierungSerialization

Wenn Sie Nachrichtenverträge oder Parameter zum Beschreiben des Nachrichteninhalts verwenden, müssen Sie die Serialisierung für die Konvertierung zwischen .NET Framework.NET Framework -Typ- und XML-Infoset-Darstellung verwenden.Whenever you use message contracts or parameters to describe message contents, you must use serialization to convert between .NET Framework.NET Framework types and XML Infoset representation. Die Serialisierung wird an anderen Stellen in WCFWCFverwendet. So bietet Message beispielsweise eine generische GetBody -Methode, mit der Sie den gesamten Nachrichtentext deserialisiert in ein Objekt lesen können.Serialization is used in other places in WCFWCF, for example, Message has a Generic GetBody method that you can use to read the entire body of the message deserialized into an object.

WCFWCF unterstützt zwei Serialisierungstechnologien "ohne Anpassung" zum Serialisieren und Deserialisieren von Parametern und Bestandteilen von Nachrichten: DataContractSerializer und XmlSerializer. supports two serialization technologies "out of the box" for serializing and deserializing parameters and message parts: the DataContractSerializer and the XmlSerializer. Darüber hinaus können Sie benutzerdefinierte Serialisierungsprogramme schreiben.Additionally, you can write custom serializers. Andere Teile von WCFWCF (wie die generische GetBody -Methode oder die SOAP-Fehlerserialisierung) können auf die Verwendung der XmlObjectSerializer -Unterklassen (DataContractSerializer und NetDataContractSerializer, jedoch nicht XmlSerializer) beschränkt sein oder können sogar für die Verwendung von DataContractSerializerfest programmiert sein.However, other parts of WCFWCF (such as the Generic GetBody method or SOAP fault serialization) may be restricted to use only the XmlObjectSerializer subclasses (DataContractSerializer and NetDataContractSerializer, but not the XmlSerializer), or may even be hard-coded to use only the DataContractSerializer.

Der XmlSerializer ist das in ASP.NETASP.NET -Webdiensten verwendete Serialisierungsmodul.The XmlSerializer is the serialization engine used in ASP.NETASP.NET Web services. DataContractSerializer ist das neue Serialisierungsmodul, das das neue Datenvertrags-Programmiermodell versteht.The DataContractSerializer is the new serialization engine that understands the new data contract programming model. DataContractSerializer ist die Standardauswahl. Die Entscheidung für die Verwendung von XmlSerializer kann mit dem DataContractFormatAttribute für einzelne Vorgänge getroffen werden.DataContractSerializer is the default choice, and the choice to use the XmlSerializer can be made on a per-operation basis using the DataContractFormatAttribute attribute.

DataContractSerializerOperationBehavior und XmlSerializerOperationBehavior sind die Vorgangsverhalten, die für das Plug-In der Nachrichtenformatierungsprogramme für DataContractSerializer und XmlSerializerverantwortlich sind.DataContractSerializerOperationBehavior and XmlSerializerOperationBehavior are the operation behaviors responsible for plugging in the message formatters for the DataContractSerializer and the XmlSerializer, respectively. Das DataContractSerializerOperationBehavior -Verhalten kann mit jedem Serialisierungsprogramm funktionieren, das von XmlObjectSerializerabgeleitet wird, u.&#160;a. NetDataContractSerializer (ausführlich beschrieben unter "Verwenden der eigenständigen Serialisierung").The DataContractSerializerOperationBehavior behavior can actually operate with any serializer that derives from XmlObjectSerializer, including the NetDataContractSerializer (described in detail in Using Stand-Alone Serialization). Das Verhalten ruft eine der virtuellen CreateSerializer -Methodenüberladungen auf, um das Serialisierungsprogramm zu erhalten.The behavior calls one of the CreateSerializer virtual method overloads to obtain the serializer. Um ein anderes Serialisierungsprogramm zu verwenden, erstellen Sie eine neue DataContractSerializerOperationBehavior -Unterklasse und überschreiben beide CreateSerializer -Überladungen.To plug in a different serializer, create a new DataContractSerializerOperationBehavior subclass and override both CreateSerializer overloads.

Siehe auchSee Also

Angeben von Datenübertragung in DienstverträgenSpecifying Data Transfer in Service Contracts