Panoramica dell'architettura di trasferimento dei datiData Transfer Architectural Overview

Windows Communication Foundation (WCF) può essere considerato come un'infrastruttura di messaggistica.Windows Communication Foundation (WCF) can be thought of as a messaging infrastructure. Può ricevere messaggi, elaborarli e inviarli a codice utente per ulteriori azioni, oppure può costruire messaggi dai dati forniti dal codice utente e recapitarli a una destinazione.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 questo argomento, rivolto agli sviluppatori avanzati, viene illustrata l'architettura per la gestione dei messaggi e dei dati in essi contenuti.This topic, which is intended for advanced developers, describes the architecture for handling messages and the contained data. Per informazioni più semplici e orientate alle attività su come inviare e ricevere dati, vedere 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.

Nota

In questo argomento vengono illustrati i dettagli di implementazione WCF che non sono visibili esaminando il modello a oggetti WCF.This topic discusses WCF implementation details that are not visible by examining the WCF object model. In merito ai dettagli di implementazione documentati, è opportuno precisare due cose.Two words of caution are in order with regard to documented implementation details. In primo luogo, le descrizioni sono semplificate. L'implementazione effettiva potrebbe essere più complessa a causa delle ottimizzazioni o di altre ragioni.First, the descriptions are simplified; actual implementation may be more complex due to optimizations or other reasons. In secondo luogo, non fare mai affidamento su dettagli specifici di implementazione, nemmeno su quelli documentati, poiché possono cambiare senza preavviso da una versione all'altra o anche in una Service Release.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.

Architettura di baseBasic Architecture

Un elemento fondamentale delle funzionalità di gestione dei messaggi WCF è il Message (classe), descritto dettagliatamente in mediante la classe messaggio.At the core of WCF message-handling capabilities is the Message class, which is described in detail in Using the Message Class. I componenti runtime di WCF possono essere suddivisi in due parti principali: lo stack dei canali e il framework del servizio con il Message classe che è il punto di connessione.The run-time components of WCF can be divided into two major parts: the channel stack and the service framework, with the Message class being the connection point.

Lo stack dei canali è responsabile della conversione tra un'istanza Message valida e una qualche azione che corrisponde all'invio o alla ricezione di dati del messaggio.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. Sul lato di invio, lo stack dei canali prende un'istanza Message valida e, dopo averla elaborata, esegue un'azione che corrisponde in modo logico all'invio del messaggio.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. L'azione potrebbe essere l'invio di pacchetti TCP o HTTP, la messa in coda del messaggio nel sistema di Accodamento messaggi, la scrittura del messaggio in un database, il suo salvataggio in una condivisione file o una qualsiasi altra azione, a seconda dell'implementazione.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. L'azione più comune è l'invio del messaggio su un protocollo di rete.The most common action is sending the message over a network protocol. Sul lato di ricezione, accade il contrario, ovvero viene rilevata un'azione (che può essere l'arrivo di pacchetti TCP o HTTP o qualsiasi altra azione) e, dopo l'elaborazione, lo stack dei canali converte questa azione in un'istanza Message valida.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.

È possibile usare WCF utilizzando la Message classe e i stack dei canali direttamente.You can use WCF by using the Message class and the channel stack directly. Questa procedura è tuttavia difficile e lunga.However, doing so is difficult and time-consuming. Inoltre, il Message oggetto non fornisce alcun supporto di metadati, pertanto non è possibile generare client WCF fortemente tipizzati se si utilizza WCF in questo modo.Additionally, the Message object provides no metadata support, so you cannot generate strongly typed WCF clients if you use WCF in this manner.

Pertanto, WCF include un framework del servizio che fornisce un modello di programmazione di facile utilizzo che è possibile utilizzare per costruire e ricevere Message oggetti.Therefore, WCF includes a service framework that provides an easy-to-use programming model that you can use to construct and receive Message objects. Il framework del servizio esegue il mapping dei servizi ai tipi .NET Framework.NET Framework attraverso la nozione dei contratti di servizio e invia messaggi a operazioni utente che sono semplicemente metodi .NET Framework.NET Framework contrassegnati con l'attributo OperationContractAttribute . Per altre informazioni, vedere 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). Tali metodi possono avere parametri e valori restituiti.These methods may have parameters and return values. Sul lato del servizio, il framework del servizio converte le istanze Message in ingresso in parametri e i valori restituiti in istanze Message in uscita.On the service side, the service framework converts incoming Message instances into parameters and converts return values into outgoing Message instances. Nel lato client, avviene il contrario.On the client side, it does the opposite. Si consideri ad esempio l'operazione FindAirfare seguente.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

Si supponga che FindAirfare venga chiamato nel client.Suppose FindAirfare is called on the client. Il framework del servizio nel client converte i parametri FromCity e ToCity in un'istanza Message in uscita e la passa allo stack dei canali perché venga inviata.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.

Nel lato del servizio, quando un'istanza Message arriva dallo stack dei canali, il framework del servizio estrae i dati pertinenti dal messaggio per popolare i parametri FromCity e ToCity , quindi chiama il metodo FindAirfare nel lato servizio.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. Quando il metodo restituisce il risultato, il framework del servizio prende il valore integer restituito e il parametro di output IsDirectFlight e crea un'istanza dell'oggetto Message che contiene queste informazioni.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. Passa quindi l'istanza Message allo stack dei canali affinché venga inviata di nuovo al client.It then passes the Message instance to the channel stack to be sent back to the client.

Sul lato client, dallo stack dei canali emerge un'istanza Message che contiene il messaggio di risposta.On the client side, a Message instance that contains the response message emerges from the channel stack. Il framework del servizio estrae il valore restituito e il valore IsDirectFlight e li restituisce al chiamante del client.The service framework extracts the return value and the IsDirectFlight value and returns these to the caller of the client.

Classe di messaggiMessage Class

La classe Message è intesa per essere una rappresentazione astratta di un messaggio, ma la sua progettazione è fortemente legata al messaggio SOAP.The Message class is intended to be an abstract representation of a message, but its design is strongly tied to the SOAP message. Un Message contiene tre informazioni principali: il corpo, le intestazioni e le proprietà del messaggio.A Message contains three major pieces of information: a message body, message headers, and message properties.

Corpo del messaggioMessage Body

Il corpo del messaggio ha lo scopo di rappresentare il payload effettivo dei dati del messaggio.The message body is intended to represent the actual data payload of the message. Il corpo del messaggio è sempre rappresentato come un Infoset XML.The message body is always represented as an XML Infoset. Questo non significa che tutti i messaggi creati o ricevuti in WCF devono essere in formato XML.This does not mean that all messages created or received in WCF must be in XML format. È lo stack dei canali a decidere come interpretare il corpo del messaggio.It is up to the channel stack to decide how to interpret the message body. Può emetterlo come XML, convertirlo in un altro formato o anche ometterlo completamente.It may emit it as XML, convert it to some other format, or even omit it entirely. Naturalmente, con la maggior parte delle associazioni WCF forniture, il corpo del messaggio è rappresentato come contenuto XML nella sezione del corpo di una SOAP envelope.Of course, with most of the bindings WCF supplies, the message body is represented as XML content in the body section of a SOAP envelope.

È importante comprendere che la classe Message non contiene necessariamente un buffer con dati XML che rappresentano il corpo.It is important to realize that the Message class does not necessarily contain a buffer with XML data representing the body. Logicamente, Message contiene un Infoset XML, che può essere creato dinamicamente e può non essere mai fisicamente presente in memoria.Logically, Message contains an XML Infoset, but this Infoset may be dynamically constructed and may never physically exist in memory.

Inserimento di dati nel corpo del messaggioPutting Data into the Message Body

Non esiste un meccanismo uniforme per inserire dati in un corpo del messaggio.There is no uniform mechanism to put data into a message body. La classe Message ha un metodo astratto, OnWriteBodyContents(XmlDictionaryWriter), che prende un XmlDictionaryWriter.The Message class has an abstract method, OnWriteBodyContents(XmlDictionaryWriter), which takes an XmlDictionaryWriter. Ogni sottoclasse della classe Message è responsabile dell'esecuzione dell'override di questo metodo e della scrittura del suo contenuto.Each subclass of the Message class is responsible for overriding this method and writing out its own contents. Il corpo del messaggio contiene logicamente l'Infoset XML prodotto da OnWriteBodyContent .The message body logically contains the XML Infoset that OnWriteBodyContent produces. Si consideri ad esempio la sottoclasse seguente Message .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

Fisicamente, un'istanza AirfareRequestMessage contiene solo due stringhe ("fromCity" e "toCity").Physically, an AirfareRequestMessage instance contains only two strings ("fromCity" and "toCity"). Tuttavia, il messaggio contiene logicamente l'infoset XML seguente:However, logically the message contains the following XML infoset:

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

In genere questo non è il metodo utilizzato per creare messaggi, perché è possibile utilizzare il framework del servizio per creare un messaggio come il precedente dai parametri del contratto dell'operazione.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. La classe Message , inoltre, ha metodi CreateMessage statici che è possibile utilizzare per creare messaggi con tipi di contenuto comuni: un messaggio vuoto, un messaggio che contiene un oggetto serializzato in XML con DataContractSerializer, un messaggio che contiene un errore SOAP, un messaggio che contiene XML rappresentato da un XmlReadere così via.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.

Ottenimento di dati da un corpo del messaggioGetting Data from a Message Body

Esistono due modalità principali per estrarre i dati archiviati in un corpo del messaggio:You can extract the data stored in a message body in two main ways:

  • È possibile ottenere l'intero corpo del messaggio chiamando il metodo WriteBodyContents(XmlDictionaryWriter) e passando contemporaneamente un writer XML.You can get the entire message body at one time by calling the WriteBodyContents(XmlDictionaryWriter) method and passing in an XML writer. L'intero corpo del messaggio viene scritto in questo writer.The complete message body is written out to this writer. L'ottenimento contemporaneo dell'intero corpo del messaggio viene detto anche scrittura di un messaggio.Getting the entire message body at one time is also called writing a message. La scrittura viene eseguita principalmente dallo stack dei canali all'invio dei messaggi. Parte dello stack dei canali di solito otterrà l'accesso all'intero corpo del messaggio, lo codificherà e l'invierà.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.

  • Un'altra modalità per estrarre informazioni dal corpo del messaggio consiste nel chiamare GetReaderAtBodyContents() e ottenere un lettore XML.Another way to get information out of the message body is to call GetReaderAtBodyContents() and get an XML reader. Se necessario, sarà quindi possibile accedere al corpo del messaggio in sequenza, chiamando i metodi nel lettore.The message body can then be accessed sequentially as needed by calling methods on the reader. L'ottenimento del corpo del messaggio un pezzo alla volta viene detto anche lettura di un messaggio.Getting the message body piece-by-piece is also called reading a message. La lettura del messaggio è utilizzata principalmente dal framework del servizio alla ricezione dei messaggi.Reading the message is primarily used by the service framework when receiving messages. Quando, ad esempio, è utilizzato DataContractSerializer , il framework del servizio otterrà un lettore XML sul corpo e lo passerà al motore di deserializzazione che avvierà la lettura del messaggio, elemento per elemento, e costruirà l'oggetto grafico corrispondente.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.

Un corpo del messaggio può essere recuperato solo una volta.A message body can be retrieved only once. Ciò consente di lavorare con flussi di tipo forward-only.This makes it possible to work with forward-only streams. È ad esempio possibile scrivere un override OnWriteBodyContents(XmlDictionaryWriter) che legge da un FileStream e restituisce i risultati come Infoset XML.For example, you can write an OnWriteBodyContents(XmlDictionaryWriter) override that reads from a FileStream and returns the results as an XML Infoset. Non sarà mai necessario "Riavvolgi" all'inizio del file.You will never need to "rewind" to the beginning of the file.

I metodi WriteBodyContents e GetReaderAtBodyContents controllano semplicemente che il corpo del messaggio non sia mai stato recuperato, quindi chiamano rispettivamente OnWriteBodyContents o OnGetReaderAtBodyContents.The WriteBodyContents and GetReaderAtBodyContents methods simply check that the message body has never been retrieved before, and then call OnWriteBodyContents or OnGetReaderAtBodyContents, respectively.

Utilizzo di messaggi in WCFMessage Usage in WCF

La maggior parte dei messaggi può essere classificata come in uscita (quelli che vengono creati dal framework del servizio per essere inviati dallo stack dei canali) o in ingresso (quelli che arrivano dallo stack dei canali e sono interpretati dal framework del servizio).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). Lo stack di canali può inoltre operare in modalità di memorizzazione nel buffer o in modalità flusso.Furthermore, the channel stack can operate in either buffered or streaming mode. Il framework del servizio può anche esporre un modello di programmazione con o senza invio nel flusso.The service framework may also expose a streamed or nonstreamed programming model. Ciò porta ai casi elencati nella tabella seguente assieme ai dettagli semplificati della loro implementazione.This leads to the cases listed in the following table, along with simplified details of their implementation.

Tipo messaggioMessage type Dati del corpo nel messaggioBody data in message Implementazione della scrittura (OnWriteBodyContents)Write (OnWriteBodyContents) implementation Implementazione della lettura (OnGetReaderAtBodyContents)Read (OnGetReaderAtBodyContents) Implementation
In uscita, creato da un modello di programmazione senza invio nel flussoOutgoing, created from nonstreamed programming model I dati necessario per scrivere il messaggio (ad esempio, un oggetto e l'istanza DataContractSerializer necessaria per serializzarlo)*The data needed to write the message (for example, an object and the DataContractSerializer instance needed to serialize it)* Logica personalizzata per scrivere il messaggio sulla base dei dati archiviati (ad esempio, chiamare WriteObject su DataContractSerializer se questo è il serializzatore utilizzato)*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)* Chiamare OnWriteBodyContents, memorizzare nel buffer i risultati, restituire un lettore XML sul bufferCall OnWriteBodyContents, buffer the results, return an XML reader over the buffer
In uscita, creato dal modello di programmazione con invio nel flussoOutgoing, created from streamed programming model Stream con i dati da scrivere*The Stream with the data to be written* Scrivere i dati dal flusso archiviato utilizzando il meccanismo IStreamProvider *Write out data from the stored stream using the IStreamProvider mechanism* Chiamare OnWriteBodyContents, memorizzare nel buffer i risultati, restituire un lettore XML sul bufferCall OnWriteBodyContents, buffer the results, return an XML reader over the buffer
In ingresso dallo stack dei canali del flussoIncoming from streaming channel stack Un oggetto Stream che rappresenta i dati che entrano sulla rete con un XmlReader su di essoA Stream object that represents the data coming in over the network with an XmlReader over it Scrivere il contenuto dal XmlReader archiviato utilizzando WriteNodeWrite out the contents from the stored XmlReader using WriteNode Restituisce il XmlReaderarchiviatoReturns the stored XmlReader
In ingresso dallo stack dei canali senza utilizzo del flussoIncoming from nonstreaming channel stack Un buffer che contiene dati del corpo con un XmlReader su di essoA buffer that contains body data with an XmlReader over it Scrive il contenuto dal XmlReader archiviato utilizzando WriteNodeWrites out the contents from the stored XmlReader using WriteNode Restituisce il lang archiviatoReturns the stored lang

* Questi elementi non vengono implementati direttamente nelle Message sottoclassi, ma in sottoclassi della BodyWriter classe.* These items are not implemented directly in Message subclasses, but in subclasses of the BodyWriter class. Per altre informazioni su BodyWriter, vedere Using the Message Class.For more information about the BodyWriter, see Using the Message Class.

Intestazioni del messaggioMessage Headers

Un messaggio può contenere intestazioni.A message may contain headers. Un'intestazione è costituita in modo logico da un Infoset XML a cui sono associati un nome, uno spazio dei nomi e alcune altre proprietà.A header logically consists of an XML Infoset that is associated with a name, a namespace, and a few other properties. Alle intestazioni messaggio si accede utilizzando la proprietà Headers su Message.Message headers are accessed using the Headers property on Message. Ogni intestazione è rappresentata da una classe MessageHeader .Each header is represented by a MessageHeader class. Le intestazioni messaggio in genere vengono mappate su intestazioni messaggio SOAP quando si utilizza uno stack dei canali configurato per lavorare con messaggi SOAP.Normally, message headers are mapped to SOAP message headers when using a channel stack configured to work with SOAP messages.

L'inserimento e l'estrazione di informazioni in e da un'intestazione messaggio sono simili all'utilizzo del corpo del messaggio.Putting information into a message header and extracting information from it is similar to using the message body. Il processo è leggermente semplificato perché il flusso non è supportato.The process is somewhat simplified because streaming is not supported. È possibile accedere al contenuto della stessa intestazione più di una volta e accedere alle intestazioni in ordine arbitrario, forzando le intestazioni a essere sempre memorizzate nel buffer.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. Non esiste un meccanismo generico disponibile per ottenere un lettore XML su un'intestazione, ma è presente un MessageHeader sottoclasse interno a WCF che rappresenta un'intestazione leggibile con tale funzionalità.There is no general-purpose mechanism available to get an XML reader over a header, but there is a MessageHeader subclass internal to WCF that represents a readable header with such a capability. Questo tipo di MessageHeader viene creato dallo stack dei canali all'arrivo di un messaggio con intestazioni dell'applicazione personalizzate.This type of MessageHeader is created by the channel stack when a message with custom application headers comes in. Ciò consente al framework del servizio di utilizzare un motore di deserializzazione, ad esempio DataContractSerializer, per interpretare queste intestazioni.This enables the service framework to use a deserialization engine, such as the DataContractSerializer, to interpret these headers.

Per altre informazioni, vedere utilizzando la classe messaggio.For more information, see Using the Message Class.

Proprietà del messaggioMessage Properties

Un messaggio può contenere proprietà.A message may contain properties. Una proprietà è qualsiasi oggetto .NET Framework.NET Framework associato a un nome di stringa.A property is any .NET Framework.NET Framework object that is associated with a string name. Alle proprietà si accede tramite la proprietà Properties su Message.Properties are accessed through the Properties property on Message.

Contrariamente al corpo del messaggio e alle intestazioni messaggio (che in genere eseguono il mapping rispettivamente al corpo SOAP e alle intestazioni SOAP), le proprietà normalmente non vengono inviate o ricevute insieme ai messaggi.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. La funzione principale delle proprietà del messaggio è quella di fungere da meccanismo di comunicazione per passare dati sul messaggio tra i vari canali nello stack dei canali e tra lo stack dei canali e il modello di servizio.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.

Ad esempio, il canale di trasporto HTTP incluso come parte di WCF è in grado di produrre vari codici di stato HTTP, ad esempio "404 (non trovato)" e "500 (errore interno del Server)," quando invia risposte ai client.For example, the HTTP transport channel included as part of WCF is capable of producing various HTTP status codes, such as "404 (Not Found)" and "500 (Internal Server Error)," when it sends replies to clients. Prima di inviare un messaggio di risposta, viene verificato se il Properties del Message contengono una proprietà chiamata "httpResponse" che contiene un oggetto di tipo 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. Se tale proprietà risulta presente, esaminerà la proprietà StatusCode e utilizzerà quel codice di stato.If such a property is found, it will look at the StatusCode property and use that status code. Se non la trova, viene utilizzato il codice predefinito "200 (OK)".If it is not found, the default "200 (OK)" code is used.

Per altre informazioni, vedere utilizzando la classe messaggio.For more information, see Using the Message Class.

Il messaggio nel suo insiemeThe Message as a Whole

Finora, sono stati illustrati i metodi per accedere separatamente alle varie parti del messaggio.So far, we have discussed methods for accessing the various parts of the message in isolation. La classe Message fornisce tuttavia anche dei metodi per lavorare su tutto il messaggio.However, the Message class also provides methods to work with the entire message as a whole. Il metodo WriteMessage , ad esempio, scrive l'intero messaggio in un writer XML.For example, the WriteMessage method writes out the entire message to an XML writer.

Affinché ciò sia possibile, è necessario definire un mapping tra l'intera istanza Message e un Infoset XML.For this to be possible, a mapping must be defined between the entire Message instance and an XML Infoset. Questo mapping, di fatto, esiste: WCF utilizza lo standard SOAP per definirlo.Such a mapping, in fact, exists: WCF uses the SOAP standard to define this mapping. Quando un'istanza Message viene scritta come Infoset XML, l'Infoset risultante è la SOAP envelope valida che contiene il messaggio.When a Message instance is written out as an XML Infoset, the resulting Infoset is the valid SOAP envelope that contains the message. Pertanto, WriteMessage eseguirebbe in genere i passaggi seguenti:Thus, WriteMessage would normally perform the following steps:

  1. Scrivere il tag di apertura dell'elemento SOAP envelope.Write the SOAP envelope element opening tag.

  2. Scrivere il tag di apertura dell'elemento intestazione SOAP, scrivere tutte le intestazioni e chiudere l'elemento intestazione.Write the SOAP header element opening tag, write out all of the headers, and close the header element.

  3. Scrivere il tag di apertura dell'elemento corpo SOAP.Write the SOAP body element opening tag.

  4. Chiamare WriteBodyContents o un metodo equivalente per scrivere il corpo.Call WriteBodyContents or an equivalent method to write out the body.

  5. Chiudere gli elementi corpo ed envelope.Close the body and envelope elements.

I passaggi precedenti sono strettamente legati allo standard SOAP.The preceding steps are closely tied to the SOAP standard. Una complicazione deriva dal fatto che esistono più versioni di SOAP. È ad esempio impossibile scrivere correttamente l'elemento SOAP envelope senza sapere qual è la versione SOAP utilizzata.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. In alcuni casi, inoltre, potrebbe essere auspicabile disattivare completamente questo mapping complesso specifico di SOAP.Also, in some cases, it may be desirable to turn off this complex SOAP-specific mapping completely.

A tale scopo, in Version viene fornita una proprietà Message.For these purposes, a Version property is provided on Message. Può essere impostata sulla versione SOAP da utilizzare quando si scrive il messaggio, oppure su None per impedire qualsiasi mapping specifico di SOAP.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. Se la proprietà Version è impostata su None, i metodi che lavorano con il messaggio intero operano come se il messaggio fosse costituito unicamente dal suo corpo. WriteMessage , ad esempio, chiamerebbe semplicemente WriteBodyContents invece di eseguire i diversi passaggi elencati sopra.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. È previsto che, sui messaggi in arrivo, Version verrà automaticamente rilevata e impostata correttamente.It is expected that on incoming messages, Version will be auto-detected and set correctly.

Stack dei canaliThe Channel Stack

CanaliChannels

Come già indicato, lo stack dei canali è responsabile della conversione di istanze Message in uscita in un'azione (ad esempio l'invio di pacchetti sulla rete) o della conversione di un'azione (ad esempio la ricezione di pacchetti di rete) in istanze Message in ingresso.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.

Lo stack dei canali è composto da uno o più canali ordinati in una sequenza.The channel stack is composed of one or more channels ordered in a sequence. Un'istanza Message in uscita viene passata al primo canale nello stack (chiamato anche canale superiore) che lo passa al canale successivo lungo lo stack e così via.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. Il messaggio termina nell'ultimo canale, chiamato canale di trasporto.The message terminates in the last channel, which is called the transport channel. I messaggi in arrivo hanno origine nel canale di trasporto e vengono passati di canale in canale lungo lo stack.Incoming messages originate in the transport channel and are passed from channel to channel up the stack. Dal canale principale, il messaggio viene in genere passato nel framework del servizio.From the topmost channel, the message is usually passed into the service framework. Anche se questo è il modello abituale per i messaggi dell'applicazione, alcuni canali potrebbero funzionare in modo leggermente diverso. Potrebbero, ad esempio, inviare i messaggi della propria infrastruttura senza che venga loro passato un messaggio da un canale superiore.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.

I canali possono operare sul messaggio in vari modi, mentre transita nello stack.Channels may operate on the message in various ways as it passes through the stack. L'operazione più comune consiste nell'aggiungere un'intestazione a un messaggio in uscita e nel leggere le intestazioni in un messaggio in arrivo.The most common operation is adding a header to an outgoing message and reading headers on an incoming message. Un canale può, ad esempio, calcolare la firma digitale di un messaggio e aggiungerla come intestazione.For example, a channel may compute the digital signature of a message and add it as a header. Un canale può anche controllare tale intestazione di firma digitale sui messaggi in arrivo e impedire che quelli senza una firma valida risalgano lo stack dei canali.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. I canali, inoltre, spesso impostano o controllano le proprietà dei messaggi.Channels also often set or inspect message properties. Il corpo del messaggio è in genere non viene modificato, anche se ciò è consentito, ad esempio, il canale di sicurezza WCF può crittografare al corpo del messaggio.The message body is usually not modified, although this is allowed, for example, the WCF security channel can encrypt the message body.

Canali di trasporto e codificatori di messaggiTransport Channels and Message Encoders

Il canale inferiore nello stack è responsabile della trasformazione effettiva in un'azione di un Messagein uscita, modificato da altri canali.The bottommost channel in the stack is responsible for actually transforming an outgoing Message, as modified by other channels, into some action. Sul lato ricevente, questo è il canale che converte un'azione in un Message che viene elaborato dagli altri canali.On the receive side, this is the channel that converts some action into a Message that other channels process.

Come già indicato, le azioni possono essere diverse: invio o ricezione di pacchetti di rete su vari protocolli, lettura o scrittura del messaggio in un database, oppure messa in coda o rimozione del messaggio da una coda di Accodamento messaggi e così via.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. Tutte queste azioni hanno una cosa in comune: richiedono una trasformazione tra WCFMessage istanza e un gruppo effettivo di byte che possono essere inviati, ricevuti, letti, scritti, in coda o rimossi dalla coda.All these actions have one thing in common: they require a transformation between the WCFMessage instance and an actual group of bytes that can be sent, received, read, written, queued, or dequeued. Il processo di conversione di un Message in un gruppo di byte è detto codifica, mentre il processo inverso di creazione di un Message da un gruppo di byte è detto decodifica.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.

La maggior parte dei canali di trasporto utilizza componenti detti codificatori di messaggi destinati ad eseguire la codifica e la decodifica.Most transport channels use components called message encoders to accomplish the encoding and decoding work. Un codificatore di messaggi è una sottoclasse della classe MessageEncoder .A message encoder is a subclass of the MessageEncoder class. MessageEncoder include vari overload dei metodi ReadMessage e WriteMessage per eseguire la conversione tra Message e gruppi di byte.MessageEncoder includes various ReadMessage and WriteMessage method overloads to convert between Message and groups of bytes.

Sul lato di invio, un canale di trasporto di memorizzazione nel buffer passa l'oggetto Message ricevuto da un canale sovrastante a WriteMessage.On the sending side, a buffering transport channel passes the Message object that it received from a channel above it to WriteMessage. Di ritorno, riceve una matrice di byte che utilizzerà poi per eseguire l'azione (ad esempio assemblare questi byte come pacchetti TCP validi e inviarli alla destinazione corretta).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). Un canale di trasporto del flusso crea innanzitutto un Stream (ad esempio, sulla connessione TCP in uscita), quindi passa sia lo Stream che il Message da inviare all'overload WriteMessage appropriato che scrive il messaggio.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.

Sul lato ricevente, un canale di trasporto di memorizzazione nel buffer estrae i byte in ingresso (ad esempio, dai pacchetti TCP in ingresso) in una matrice e chiama ReadMessage per ottenere un oggetto Message che può passare più avanti nello stack dei canali.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. Un canale di trasporto del flusso crea un oggetto Stream (ad esempio, un flusso di rete sulla connessione TCP in ingresso) e lo passa a ReadMessage per ottenere un oggetto Message .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.

La separazione tra i canali di trasporto e il codificatore di messaggi non è obbligatoria. È possibile scrivere un canale di trasporto che non utilizza un codificatore di messaggi.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. Il vantaggio di questa separazione, tuttavia, è la facilità di composizione.However, the advantage of this separation is ease of composition. Finché un canale di trasporto utilizza solo la base MessageEncoder, può funzionare con qualsiasi WCF o un codificatore di messaggi di terze parti.As long as a transport channel uses only the base MessageEncoder, it can work with any WCF or third-party message encoder. Analogamente, lo stesso codificatore può essere normalmente utilizzato in qualsiasi canale di trasporto.Likewise, the same encoder can normally be used in any transport channel.

Operazione del codificatore messaggiMessage Encoder Operation

Per descrivere l'operazione tipica di un codificatore, è opportuno considerare i quattro casi seguenti.To describe the typical operation of an encoder, it is useful to consider the following four cases.

OperazioneOperation CommentoComment
Codifica, memorizzata nel bufferEncoding, Buffered In modalità di memorizzazione nel buffer, il codificatore crea un buffer di dimensioni variabili, dopo di che crea un writer XML su di esso.In buffered mode, the encoder normally creates a variable-size buffer and then creates an XML writer over it. Chiama quindi WriteMessage(XmlWriter) sul messaggio in fase di codifica, per scrivere le intestazioni e il corpo utilizzando WriteBodyContents(XmlDictionaryWriter), come spiegato nella sezione precedente di questo argomento su Message .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. Viene infine restituito il contenuto del buffer (rappresentato come matrice di byte) che deve essere utilizzato dal canale di trasporto.The contents of the buffer (represented as an array of bytes) are then returned for the transport channel to use.
Codifica, trasmessaEncoding, Streamed In modalità con invio nel flusso, l'operazione è simile a quanto sopra, ma più semplice.In streamed mode, the operation is similar to the above, but simpler. Non è necessario alcun buffer.There is no need for a buffer. In genere viene creato un writer XML sopra il flusso e viene chiamato WriteMessage(XmlWriter) sul Message per scriverlo in questo writer.An XML writer is normally created over the stream and WriteMessage(XmlWriter) is called on the Message to write it out to this writer.
Decodifica, memorizzata nel bufferDecoding, Buffered In caso di decodifica in modalità di memorizzazione nel buffer, in genere viene creata una speciale sottoclasse Message che contiene i dati memorizzati nel buffer.When decoding in buffered mode, a special Message subclass that contains the buffered data is normally created. Vengono lette le intestazioni messaggio e viene creato un lettore XML posizionato sul corpo del messaggio.The headers of the message are read, and an XML reader positioned on the message body is created. Si tratta del lettore che verrà restituito con GetReaderAtBodyContents().This is the reader that will be returned with GetReaderAtBodyContents().
Decodifica, trasmessaDecoding, Streamed In caso di decodifica in modalità con invio nel flusso, in genere viene creata una speciale sottoclasse messaggio.When decoding in streamed mode, a special Message subclass is normally created. Il flusso viene fatto avanzare solo quel tanto che è sufficiente per leggere tutte le intestazioni e posizionarlo sul corpo del messaggio.The stream is advanced just enough to read all the headers and position it on the message body. Sul flusso viene quindi creato un lettore XML.An XML reader is then created over the stream. Si tratta del lettore che verrà restituito con GetReaderAtBodyContents().This is the reader that will be returned with GetReaderAtBodyContents().

I codificatori possono eseguire anche altre funzioni.Encoders can perform other functions as well. Possono, ad esempio, inserire in un pool i lettori e i writer XML.For example, the encoders can pool XML readers and writers. Creare un nuovo lettore o writer XML ogni volta che è richiesto, è oneroso.It is expensive to create a new XML reader or writer every time one is needed. I codificatori, pertanto, gestiscono un pool di lettori e un pool di writer di dimensioni configurabili.Therefore, encoders normally maintain a pool of readers and a pool of writers of configurable size. Nelle descrizioni dell'operazione del codificatore descritto in precedenza, ogni volta che la frase "Creazione di un lettore/writer XML" viene utilizzati, in genere, "richiedere uno dal pool oppure crearlo se non è disponibile."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." Il codificatore (insieme alle sottoclassi Message che crea durante la decodifica) contiene la logica necessaria per restituire lettori e scrittori ai pool quando non sono più necessari, ad esempio quando Message viene chiuso.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).

WCF fornisce tre codificatori di messaggi, anche se è possibile crearne tipi aggiuntivi personalizzati.WCF provides three message encoders, although it is possible to create additional custom types. I tipi forniti sono testo, binario e MTOM (Message Transmission Optimization Mechanism).The supplied types are Text, Binary, and Message Transmission Optimization Mechanism (MTOM). La descrizione dettagliata è disponibile in Choosing a Message Encoder.These are described in detail in Choosing a Message Encoder.

Interfaccia IStreamProviderThe IStreamProvider Interface

Quando si scrive in un writer XML un messaggio in uscita che contiene un corpo inviato nel flusso, Message utilizza una sequenza di chiamate simili alle seguenti nell'implementazione di OnWriteBodyContents(XmlDictionaryWriter) :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:

  • Scrivere tutte le informazioni necessarie che precedono il flusso (ad esempio, il tag di apertura XML).Write any necessary information preceding the stream (for example, the opening XML tag).

  • Scrivere il flusso.Write the stream.

  • Scrivere tutte le informazioni dopo il flusso (ad esempio, il tag di chiusura XML).Write any information following the stream (for example, the closing XML tag).

Questa procedura funziona bene con codifiche simili alla codifica XML testuale.This works well with encodings that are similar to the textual XML encoding. Esistono, tuttavia, alcune codifiche che non inseriscono informazioni InfoSet XML (ad esempio, i tag di inizio e fine di elementi XML) insieme ai dati contenuti all'interno di elementi.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. Nella codifica MTOM, ad esempio, il messaggio è suddiviso in più parti.For example, in the MTOM encoding, the message is split into multiple parts. Una parte contiene l'InfoSet XML, che può contenere riferimenti ad altre parti per il contenuto effettivo degli elementi.One part contains the XML Infoset, which may contain references to other parts for actual element contents. Dato che, in genere, l'InfoSet XML è di piccole dimensioni rispetto al contenuto inviato nel flusso, è consigliabile memorizzarlo nel buffer, scriverlo e quindi scrivere il contenuto in un flusso.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. Ciò significa che quando viene scritto il tag dell'elemento di chiusura, il flusso non dovrebbe essere stato ancora scritto.This means that by the time the closing element tag is written, the stream should not have been written out yet.

A tale fine, viene utilizzata l'interfaccia IStreamProvider .For this purpose, the IStreamProvider interface is used. L'interfaccia ha un metodo GetStream() che restituisce il flusso da scrivere.The interface has a GetStream() method that returns the stream to be written. La modalità corretta per scrivere il corpo di un messaggio inviato in un flusso in OnWriteBodyContents(XmlDictionaryWriter) è la seguente:The correct way to write out a streamed message body in OnWriteBodyContents(XmlDictionaryWriter) is as follows:

  1. Scrivere tutte le informazioni necessarie che precedono il flusso (ad esempio, il tag di apertura XML).Write any necessary information preceding the stream (for example, the opening XML tag).

  2. Chiamare l'overload WriteValue in XmlDictionaryWriter che prende un IStreamProvider, con un'implementazione IStreamProvider che restituisce il flusso da scrivere.Call the WriteValue overload on the XmlDictionaryWriter that takes an IStreamProvider, with an IStreamProvider implementation that returns the stream to be written.

  3. Scrivere tutte le informazioni dopo il flusso (ad esempio, il tag di chiusura XML).Write any information following the stream (for example, the closing XML tag).

Con questo approccio, il writer XML può scegliere quando chiamare GetStream() e scrivere i dati inviati nel flusso.With this approach, the XML writer has a choice of when to call GetStream() and write out the streamed data. I writer XML binari e testuali, ad esempio, lo chiameranno immediatamente e scriveranno il contenuto inviato nel flusso tra il tag di inizio e quello di fine.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. Il writer MTOM può decidere di chiamare GetStream() in un secondo momento, quando è pronto per scrivere la parte appropriata del messaggio.The MTOM writer may decide to call GetStream() later, when it is ready to write the appropriate part of the message.

Rappresentazione di dati in framework del servizioRepresenting Data in the Service Framework

Come indicato nella sezione "Architettura di base" di questo argomento, il framework del servizio è la parte di WCF che, tra le altre cose, è responsabile della conversione tra un modello di programmazione intuitivo per dati del messaggio ed effettivi Message istanze.As stated in the "Basic Architecture" section of this topic, the service framework is the part of WCF that, among other things, is responsible for converting between a user-friendly programming model for message data and actual Message instances. Uno scambio di messaggi viene in genere rappresentato nel framework del servizio come metodo .NET Framework.NET Framework contrassegnato con l'attributo OperationContractAttribute .Normally, a message exchange is represented in the service framework as a .NET Framework.NET Framework method marked with the OperationContractAttribute attribute. Il metodo può prendere alcuni parametri e restituire un valore restituito o parametri out (o entrambi).The method can take in some parameters and can return a return value or out parameters (or both). Sul lato servizio, i parametri di input rappresentano il messaggio in arrivo, mentre il valore restituito e i parametri out rappresentano il messaggio in uscita.On the service side, the input parameters represent the incoming message, and the return value and out parameters represent the outgoing message. Sul lato client, è vero il contrario.On the client side, the reverse is true. Il modello di programmazione per descrivere i messaggi tramite parametri e il valore restituito vengono illustrati dettagliatamente in Specifying Data Transfer in Service Contracts.The programming model for describing messages using parameters and the return value is described in detail in Specifying Data Transfer in Service Contracts. Contenuto della sezione verrà fornita una breve panoramica.However, this section will provide a brief overview.

Modelli di programmazioneProgramming Models

Il framework del servizio WCF supporta cinque diversi modelli di programmazione per descrivere i messaggi:The WCF service framework supports five different programming models for describing messages:

1. Messaggio vuoto1. The Empty Message

Questo è il caso più semplice.This is the simplest case. Per descrivere un messaggio in arrivo vuoto, non utilizzare parametri di input.To describe an empty incoming message, do not use any input parameters.

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

Per descrivere un messaggio in uscita vuoto, utilizzare un valore restituito vuoto e non utilizzare nessun parametro out: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)

Si noti che questa procedura è diversa da un contratto dell'operazione unidirezionale: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)

Nell'esempio SetDesiredTemperature , viene illustrato un modello di scambio di messaggio bidirezionale.In the SetDesiredTemperature example, a two-way message exchange pattern is described. Dall'operazione viene restituito un messaggio, ma è vuoto.A message is returned from the operation, but it is empty. L'operazione può restituire un errore.It is possible to return a fault from the operation. Nell'esempio "Set Lightbulb", il modello di scambio di messaggi è unidirezionale, pertanto non c'è nessun messaggio in uscita da descrivere.In the "Set Lightbulb" example, the message exchange pattern is one-way, so there is no outgoing message to describe. In questo caso, il servizio non può comunicare nessuno stato al client.The service cannot communicate any status back to the client in this case.

2. Utilizzo diretto della classe messaggio2. Using the Message Class Directly

È possibile utilizzare direttamente la classe Message (o una delle sue sottoclassi) in un contratto dell'operazione.It is possible to use the Message class (or one of its subclasses) directly in an operation contract. In questo caso, il framework del servizio passa unicamente Message dall'operazione allo stack dei canali e viceversa, senza ulteriore elaborazione.In this case, the service framework just passes the Message from the operation to the channel stack and vice versa, with no further processing.

L'utilizzo diretto di Message è consigliato principalmente in due casi.There are two main use cases for using Message directly. È possibile utilizzarlo per scenari avanzati, quando nessuno degli altri modelli di programmazione offre flessibilità sufficiente per descrivere il messaggio.You can use this for advanced scenarios, when none of the other programming models gives you enough flexibility to describe your message. Si potrebbe, ad esempio, voler utilizzare file su disco per descrivere un messaggio, con le proprietà file che diventano intestazioni messaggio e il contenuto del file che diventa il corpo del messaggio.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. A questo punto, è possibile creare un codice simile al seguente.You can then create something similar to the following.

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

Il secondo utilizzo comune per Message in un contratto dell'operazione è quando un servizio non tiene conto dello specifico contenuto del messaggio e si comporta come se fosse una black box.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. Potrebbe, ad esempio, esservi un servizio che inoltra i messaggi a più destinatari diversi.For example, you might have a service that forwards messages to multiple other recipients. Il contratto può essere scritto come segue.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

L'azione = "*" riga disattiva l'invio dei messaggi e assicura che tutti i messaggi inviati al IForwardingService contratto arrivino il ForwardMessage operazione.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. (In genere, il dispatcher esaminerebbe l'intestazione del messaggio "Action" per determinare l'operazione è destinato.(Normally, the dispatcher would examine the message’s "Action" header to determine which operation it is intended for. Azione = "*" significa "tutti i valori possibili dell'intestazione dell'azione".) La combinazione di Action = "*" e l'utilizzo di messaggio come un parametro è nota come "contratto universale" perché è in grado di ricevere tutti i messaggi possibili.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. Per essere in grado di inviare tutti i messaggi possibili, utilizzare Message come valore restituito e impostare ReplyAction per "*".To be able to send all possible messages, use Message as the return value and set ReplyAction to "*". Ciò impedirà al framework del servizio di aggiungere la propria intestazione Action, permettendogli di controllarla utilizzando l'oggetto Message restituito.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. Contratti di messaggio3. Message Contracts

WCF fornisce un modello di programmazione dichiarativo per descrivere i messaggi, chiamato contratti di messaggio.WCF provides a declarative programming model for describing messages, called message contracts. Questo modello viene descritto dettagliatamente in Using Message Contracts.This model is described in detail in Using Message Contracts. Essenzialmente, tutto il messaggio è rappresentato da un singolo tipo di .NET Framework.NET Framework che utilizza attributi quali MessageBodyMemberAttribute e MessageHeaderAttribute per descrivere le parti della classe del contratto di messaggio di cui eseguire il mapping su determinate parti del messaggio.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.

I contratti di messaggio forniscono un grande controllo sulle istanze Message risultanti, anche se, ovviamente, non pari a quello assicurato dall'utilizzo diretto della classe Message .Message contracts provide a lot of control over the resulting Message instances (although obviously not as much control as using the Message class directly). I corpi dei messaggi, ad esempio, spesso sono composti da più informazioni, ognuna delle quali è rappresentata da un proprio elemento XML.For example, message bodies are often composed of multiple pieces of information, each represented by its own XML element. Questi elementi possono verificarsi direttamente nel corpo (modalitàbare ) oppure possono essere incapsulati in un elemento XML.These elements can either occur directly in the body (bare mode) or can be wrapped in an encompassing XML element. L'utilizzo del modello di programmazione di contratto di messaggio consente di decidere se utilizzare lo stile bare o quello incapsulato e controllare il nome wrapper e lo spazio dei nomi.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.

Nell'esempio di codice seguente di un contratto di messaggio vengono illustrate queste funzionalità.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

Gli elementi contrassegnati per essere serializzati (con MessageBodyMemberAttribute, MessageHeaderAttributeo altri attributi correlati) devono essere serializzabili per partecipare a un contratto di messaggio.Items marked to be serialized (with the MessageBodyMemberAttribute, MessageHeaderAttribute, or other related attributes) must be serializable to participate in a message contract. Per altre informazioni, vedere la sezione "Serializzazione" più avanti in questo argomento.For more information, see the "Serialization" section later in this topic.

4. Parametri4. Parameters

Spesso, uno sviluppatore che desidera descrivere un'operazione che influenza più blocchi di dati non ha bisogno del livello di controllo fornito dai contratti di messaggio.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. Quando si creano nuovi servizi, ad esempio, in genere non si desidera decidere se scegliere lo stile bare o quello incapsulato o il nome dell'elemento wrapper.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. Queste decisioni spesso richiedono una profonda conoscenza dei servizi Web e di SOAP.Making these decisions often requires deep knowledge of Web services and SOAP.

Il framework del servizio WCF può scegliere automaticamente la rappresentazione SOAP migliore e più interoperativa per l'invio o ricezione correlati di più informazioni, senza imporre queste scelte sull'utente.The WCF 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. A tale fine, è sufficiente descrivere queste informazioni come parametri o valori restituiti di un contratto dell'operazione.This is accomplished by simply describing these pieces of information as parameters or return values of an operation contract. Si consideri ad esempio il contratto dell'operazione seguente: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)

Il framework del servizio decide automaticamente di inserire tutte e tre le informazioni (customerID, iteme quantity) nel corpo del messaggio e di incapsularle in un elemento wrapper chiamato SubmitOrderRequest.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.

L'approccio consigliato è quello di descrivere le informazioni da inviare o ricevere come un semplice elenco di parametri del contratto dell'operazione, a meno che non vi siano delle ragioni speciali per passare al contratto di messaggio più complesso o a modelli di programmazione basati su Message.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. Flusso5. Stream

L'utilizzo di Stream o di una delle sue sottoclassi in un contratto dell'operazione o come parte unica del corpo del messaggio in un contratto di messaggio può essere considerato un modello di programmazione separato da quelli descritti sopra.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. Utilizzare Stream in questo modo è l'unica possibilità per garantire che il contratto sia utilizzabile in un flusso, a meno che non si scriva una sottoclasse Message compatibile con il flusso.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. Per altre informazioni, vedere dati di grandi dimensioni e Streaming.For more information, see Large Data and Streaming.

Quando Stream o una delle sottoclassi vengono utilizzati in questo modo, il serializzatore non viene richiamato.When Stream or one of its subclasses is used in this way, the serializer is not invoked. Per i messaggi in uscita, viene creata una sottoclasse Message speciale di flusso e il flusso viene scritto come descritto nella sezione sull'interfaccia IStreamProvider .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. Per i messaggi in arrivo, il framework del servizio crea una sottoclasse Stream sul messaggio in arrivo e la fornisce all'operazione.For incoming messages, the service framework creates a Stream subclass over the incoming message and provides it to the operation.

Restrizioni relative al modello di programmazioneProgramming Model Restrictions

I modelli di programmazione descritti sopra non possono essere combinati arbitrariamente.The programming models described above cannot be arbitrarily combined. Se, ad esempio, un'operazione accetta un tipo di contratto di messaggio, il contratto di messaggio deve essere il suo unico parametro di input.For example, if an operation accepts a message contract type, the message contract must be its only input parameter. L'operazione, inoltre, deve restituire un messaggio vuoto (il tipo restituito deve essere void) o un altro contratto di messaggio.Furthermore, the operation must then either return an empty message (return type of void) or another message contract. Queste restrizioni del modello di programmazione vengono descritte negli argomenti per ogni modello di programmazione specifico: Using Message Contracts, Using the Message Classe 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.

Formattatori dei messaggiMessage Formatters

I modelli di programmazione descritti sopra sono supportati inserendo nel framework del servizio componenti denominati formattatori dei messaggi .The programming models described above are supported by plugging in components called message formatters into the service framework. I formattatori dei messaggi sono tipi che implementano il IClientMessageFormatter o IDispatchMessageFormatter interfaccia o entrambe, da utilizzare nei client e servizio WCF, rispettivamente.Message formatters are types that implement the IClientMessageFormatter or IDispatchMessageFormatter interface, or both, for use in clients and service WCF clients, respectively.

I formattatori dei messaggi normalmente sono inseriti da comportamenti.Message formatters are normally plugged in by behaviors. DataContractSerializerOperationBehavior , ad esempio, inserisce il formattatore dei messaggi di contratto dati.For example, the DataContractSerializerOperationBehavior plugs in the data contract message formatter. Questa operazione viene eseguita sul lato servizio impostando Formatter sul formattatore corretto nel metodo ApplyDispatchBehavior(OperationDescription, DispatchOperation) oppure sul lato client impostando Formatter sul formattatore corretto nel metodo ApplyClientBehavior(OperationDescription, ClientOperation) .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.

Nelle tabelle seguenti sono elencati i metodi che possono essere implementati da un formattatore dei messaggi.The following tables lists the methods that a message formatter may implement.

InterfacciaInterface MetodoMethod OperazioneAction
IDispatchMessageFormatter DeserializeRequest(Message, Object[]) Converte un Message in ingresso in parametri dell'operazioneConverts an incoming Message to operation parameters
IDispatchMessageFormatter SerializeReply(MessageVersion, Object[], Object) Crea un Message in uscita dal valore restituito/parametri out dell'operazioneCreates an outgoing Message from operation return value/out parameters
IClientMessageFormatter SerializeRequest(MessageVersion, Object[]) Crea un Message in uscita dai parametri dell'operazioneCreates an outgoing Message from operation parameters
IClientMessageFormatter DeserializeReply(Message, Object[]) Converte un Message in ingresso in un valore restituito/parametri outConverts an incoming Message to a return value/out parameters

SerializzazioneSerialization

Ogni volta che si utilizzano contratti di messaggi o parametri per descrivere il contenuto del messaggio, è necessario utilizzare la serializzazione per la conversione tra i tipi .NET Framework.NET Framework e la rappresentazione di Infoset XML.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. La serializzazione è utilizzata in altre posizioni in WCF, ad esempio Message dispone di un oggetto generico GetBody metodo che è possibile utilizzare per leggere l'intero corpo del messaggio deserializzato in un oggetto.Serialization is used in other places in WCF, for example, Message has a Generic GetBody method that you can use to read the entire body of the message deserialized into an object.

WCF supporta due tecnologie di serializzazione "automatica" per serializzare e deserializzare parametri e parti del messaggio: il DataContractSerializer e il XmlSerializer.WCF supports two serialization technologies "out of the box" for serializing and deserializing parameters and message parts: the DataContractSerializer and the XmlSerializer. È inoltre possibile scrivere serializzatori personalizzati.Additionally, you can write custom serializers. Tuttavia, altre parti di WCF (ad esempio il tipo generico GetBody metodo o errori SOAP serializzazione) può essere limitata da utilizzare solo il XmlObjectSerializer sottoclassi (DataContractSerializer e NetDataContractSerializer, ma non il XmlSerializer), o potrebbe anche essere hard-coded utilizzino solo il DataContractSerializer.However, other parts of WCF (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.

XmlSerializer è il motore di serializzazione utilizzato nei servizi Web ASP.NETASP.NET .The XmlSerializer is the serialization engine used in ASP.NETASP.NET Web services. DataContractSerializer è il nuovo motore di serializzazione che riconosce il nuovo modello di programmazione del contratto dati.The DataContractSerializer is the new serialization engine that understands the new data contract programming model. DataContractSerializer è la scelta predefinita e la scelta di utilizzare XmlSerializer può essere fatta in base a ogni singola operazione utilizzando l'attributo DataContractFormatAttribute .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 e XmlSerializerOperationBehavior sono i comportamenti dell'operazione responsabili del collegamento dei formattatori dei messaggi rispettivamente per DataContractSerializer e XmlSerializer.DataContractSerializerOperationBehavior and XmlSerializerOperationBehavior are the operation behaviors responsible for plugging in the message formatters for the DataContractSerializer and the XmlSerializer, respectively. Il comportamento DataContractSerializerOperationBehavior può di fatto operare con qualsiasi serializzatore che deriva da XmlObjectSerializer, compreso NetDataContractSerializer (descritto in dettaglio nella sezione sull'utilizzo della serializzazione autonoma).The DataContractSerializerOperationBehavior behavior can actually operate with any serializer that derives from XmlObjectSerializer, including the NetDataContractSerializer (described in detail in Using Stand-Alone Serialization). Il comportamento chiama uno degli overload del metodo virtuale CreateSerializer per ottenere il serializzatore.The behavior calls one of the CreateSerializer virtual method overloads to obtain the serializer. Per collegare un serializzatore diverso, creare una nuova sottoclasse DataContractSerializerOperationBehavior ed eseguire l'override di entrambi gli overload CreateSerializer .To plug in a different serializer, create a new DataContractSerializerOperationBehavior subclass and override both CreateSerializer overloads.

Vedere ancheSee Also

Definizione del trasferimento dati nei contratti di servizioSpecifying Data Transfer in Service Contracts