Verwendung von NachrichtenverträgenUsing Message Contracts

Üblicherweise achten Entwickler bei der Erstellung von Windows Communication Foundation (WCF)Windows Communication Foundation (WCF)-Anwendungen streng auf die Datenstrukturen und Serialisierungsprobleme und müssen nicht auf die Struktur der Nachrichten achten, in denen die Daten transportiert werden.Typically when building Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) applications, developers pay close attention to the data structures and serialization issues and do not need to concern themselves with the structure of the messages in which the data is carried. Für diese Anwendungen ist die Erstellung von Datenverträgen für die Parameter oder Rückgabewerte ein einfacher Vorgang.For these applications, creating data contracts for the parameters or return values is straightforward. (Weitere Informationen finden Sie unterFor more information, see Angeben von Datenübertragung in Dienstverträgen.)(Weitere Informationen finden Sie unterFor more information, see Specifying Data Transfer in Service Contracts.)

Allerdings ist zuweilen die vollständige Kontrolle über die Struktur einer SOAP-Nachricht wichtiger als die Kontrolle über dessen Inhalte.However, sometimes complete control over the structure of a SOAP message is just as important as control over its contents. Dies gilt insbesondere, wenn Interoperabilität wichtig ist oder um Sicherheitsprobleme speziell auf der Ebene der Nachricht oder des Nachrichtenteils zu kontrollieren.This is especially true when interoperability is important or to specifically control security issues at the level of the message or message part. In diesen Fällen erstellen Sie eine Nachrichtenvertrag mit der Sie die Struktur der benötigten SOAP-Nachricht erforderlich angeben.In these cases, you can create a message contract that enables you to specify the structure of the precise SOAP message required.

Dieses Thema beschreibt, wie die unterschiedlichen Attribute für Nachrichtenverträge zur Erstellung eines spezifischen Nachrichtenvertrags für Ihren Vorgang verwendet werden.This topic discusses how to use the various message contract attributes to create a specific message contract for your operation.

Verwenden von Nachrichtenverträgen in VorgängenUsing Message Contracts in Operations

WCFWCFunterstützt Vorgänge, die entweder die Remoteprozeduraufruf Remoteprozeduraufruf (RPC) Stil oder messagingstil. supports operations modeled on either the remote procedure call (RPC) style or the messaging style. Bei einem Vorgang im RPC-Stil können Sie jeden serialisierbaren Typ verwenden, und Sie haben Zugriff auf die Funktionen, die für lokale Aufrufe verfügbar sind, beispielsweise mehrere Parameter sowie der ref-Parameter und der out-Parameter.In an RPC-style operation, you can use any serializable type, and you have access to the features that are available to local calls, such as multiple parameters and ref and out parameters. In diesem Stil steuert die gewählte Art der Serialisierung die Struktur der Daten in den zugrunde liegenden Nachrichten, und die WCFWCF-Laufzeit erstellt die Nachrichten, um den Vorgang zu unterstützen.In this style, the form of serialization chosen controls the structure of the data in the underlying messages, and the WCFWCF runtime creates the messages to support the operation. Dadurch können Entwickler, die sich mit SOAP und SOAP-Nachrichten nicht auskennen, Dienstanwendungen schnell und einfach erstellen und verwenden.This enables developers who are not familiar with SOAP and SOAP messages to quickly and easily create and use service applications.

Das folgende Codebeispiel zeigt einen im RPC-Stil erstellten Dienstvorgang.The following code example shows a service operation modeled on the RPC style.

[OperationContract]  
public BankingTransactionResponse PostBankingTransaction(BankingTransaction bt);  

Normalerweise ist ein Datenvertrag ausreichend, um das Schema für die Nachrichten zu definieren.Normally, a data contract is sufficient to define the schema for the messages. Beispielsweise reicht es im vorherigen Beispiel für die meisten Anwendungen aus, wenn BankingTransaction und BankingTransactionResponse über Datenverträge für die Inhaltsdefinition der zugrunde liegenden SOAP-Nachrichten verfügen.For instance, in the preceding example, it is sufficient for most applications if BankingTransaction and BankingTransactionResponse have data contracts to define the contents of the underlying SOAP messages. Weitere Informationen finden Sie unterFor more information aboutDatenverträge, finden Sie unter mithilfe von Datenverträgen. data contracts, see Using Data Contracts.

Zuweilen ist es allerdings notwendig, die Struktur der übertragenen SOAP-Nachricht genau zu steuern.However, occasionally it is necessary to precisely control how the structure of the SOAP message transmitted over the wire. Das gängigste Szenario hierfür besteht aus dem Einfügen von benutzerdefinierten SOAP-Headern.The most common scenario for this is inserting custom SOAP headers. Ein weiteres übliches Szenario ist die Definition von Sicherheitseigenschaften für Nachrichtenheader und -text, das heißt, die Entscheidung, ob diese Elemente digital signiert und verschlüsselt werden.Another common scenario is to define security properties for the message's headers and body, that is, to decide whether these elements are digitally signed and encrypted. Schließlich erfordern eine Reihe von Drittanbieter-SOAP-Stapeln Nachrichten in einem bestimmten Format.Finally, some third-party SOAP stacks require messages be in a specific format. Vorgänge im Messagingstil bieten diese Kontrolle.Messaging-style operations provide this control.

Ein Vorgang im Messagingstil verfügt über höchstens einen Parameter und einen Rückgabewert. Bei beiden Typen handelt es sich um Nachrichtentypen, d. h. sie serialisieren direkt in eine festgelegte SOAP-Nachrichtenstruktur.A messaging-style operation has at most one parameter and one return value where both types are message types; that is, they serialize directly into a specified SOAP message structure. Hierbei kann es sich um jeden Typ mit der Kennzeichnung MessageContractAttribute oder um den Message-Typ handeln.This may be any type marked with the MessageContractAttribute or the Message type. Das folgende Codebeispiel zeigt einen Vorgang, der dem vorangehenden Vorgang im RCP-Stil ähnelt, aber den Messagingstil nutzt.The following code example shows an operation similar to the preceding RCP-style, but which uses the messaging style.

Wenn sowohl BankingTransaction als auch BankingTransactionResponse Typen sind, bei denen es sich um Nachrichtenverträge handelt, ist der Code in den folgenden Vorgängen gültig.For example, if BankingTransaction and BankingTransactionResponse are both types that are message contracts, then the code in the following operations is valid.

[OperationContract]  
BankingTransactionResponse Process(BankingTransaction bt);  
[OperationContract]  
void Store(BankingTransaction bt);  
[OperationContract]  
BankingTransactionResponse GetResponse();  

Der folgende Code ist allerdings ungültig.However, the following code is invalid.

[OperationContract]  
bool Validate(BankingTransaction bt);  
// Invalid, the return type is not a message contract.  
[OperationContract]  
void Reconcile(BankingTransaction bt1, BankingTransaction bt2);  
// Invalid, there is more than one parameter.  

Für jeden Vorgang, der einen Nachrichtenvertragstyp beinhaltet und nicht eines der gültigen Muster einhält, wird eine Ausnahme ausgelöst.An exception is thrown for any operation that involves a message contract type and that does not follow one of the valid patterns. Natürlich unterliegen Vorgänge, die keine Nachrichtenvertragstypen einschließen, diesen Einschränkungen nicht.Of course, operations that do not involve message contract types are not subject to these restrictions.

Verfügt ein Typ sowohl über einen Nachrichtenvertrag als auch über einen Datenvertrag, wird nur der Nachrichtenvertrag berücksichtigt, wenn der Typ in einem Vorgang zum Einsatz kommt.If a type has both a message contract and a data contract, only its message contract is considered when the type is used in an operation.

Definition von NachrichtenverträgenDefining Message Contracts

Zur Definition eines Nachrichtenvertrags für einen Typ (d. h. zur Definition der Zuordnung zwischen Typ und SOAP-Umschlag) wenden Sie MessageContractAttribute auf den Typ an.To define a message contract for a type (that is, to define the mapping between the type and a SOAP envelope), apply the MessageContractAttribute to the type. Wenden Sie dann das MessageHeaderAttribute auf die Member an, die Sie SOAP-Headern machen möchten, und wenden Sie dann das MessageBodyMemberAttribute auf die Member an,die Sie zu Teilen des SOAP-Texts der Nachricht machen möchten.Then apply the MessageHeaderAttribute to those members of the type you want to make into SOAP headers, and apply the MessageBodyMemberAttribute to those members you want to make into parts of the SOAP body of the message.

Der folgende Code stellt ein Beispiel für die Verwendung eines Nachrichtenvertrags dar.The following code provides an example of using a message contract.

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public Operation operation;  
  [MessageHeader] public DateTime transactionDate;  
  [MessageBodyMember] private Account sourceAccount;  
  [MessageBodyMember] private Account targetAccount;  
  [MessageBodyMember] public int amount;  
}  

Bei der Verwendung dieses Typs als Vorgangsparameter wird der folgende SOAP-Umschlag generiert:When using this type as an operation parameter, the following SOAP envelope is generated:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">  
  <s:Header>  
    <h:operation xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">Deposit</h:operation>  
    <h:transactionDate xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">2012-02-16T16:10:00</h:transactionDate>  
  </s:Header>  
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
    <BankingTransaction xmlns="http://tempuri.org/">  
      <amount>0</amount>  
      <sourceAccount xsi:nil="true"/>  
      <targetAccount xsi:nil="true"/>  
    </BankingTransaction>  
  </s:Body>  
</s:Envelope>  

Beachten Sie, dass operation und transactionDate als SOAP-Header angezeigt werden und der SOAP-Text aus dem Wrapperelement BankingTransaction besteht, das sourceAccount,targetAccount und amount enthält.Notice that operation and transactionDate appear as SOAP headers and the SOAP body consists of a wrapper element BankingTransaction containing sourceAccount,targetAccount, and amount.

Sie können MessageHeaderAttribute und MessageBodyMemberAttribute auf alle Felder, Eigenschaften und Ereignisse anwenden, unabhängig davon, ob diese öffentlich, privat, geschützt oder intern sind.You can apply the MessageHeaderAttribute and MessageBodyMemberAttribute to all fields, properties, and events, regardless of whether they are public, private, protected, or internal.

Das MessageContractAttribute ermöglicht Ihnen das Angeben des WrapperName-Attributs und des WrapperNamespace-Attributs, die den Namen des Wrapperelements im Textkörper der SOAP-Nachricht steuern.The MessageContractAttribute allows you to specify the WrapperName and WrapperNamespace attributes which control the name of the wrapper element in the body of the SOAP message. Standardmäßig ist der Name des Nachrichtenvertrags Typ verwendet, für den Wrapper und den Namespace, in dem der Nachrichtenvertrag hat definiert ist HYPERLINK "http://tempuri.org/" http://tempuri.org/ wird als Standard-Namespace verwendet.By default the name of the message contract type is used for the wrapper and the namespace in which the message contract is defined HYPERLINK "http://tempuri.org/" http://tempuri.org/ is used as the default namespace.

Hinweis

KnownTypeAttribute-Attribute werden in Nachrichtenverträgen ignoriert.KnownTypeAttribute attributes are ignored in message contracts. Ist ein KnownTypeAttribute erforderlich, platzieren Sie es auf dem Vorgang, der den in Frage kommenden Nachrichtenvertrag nutzt.If a KnownTypeAttribute is required, place it on the operation that is using the message contract in question.

Kontrollieren von Header- und Textteilnamen und NamespacesControlling Header and Body Part Names and Namespaces

In der SOAP-Darstellung eines Nachrichtenvertrags wird jeder Header und jeder Textteil einem XML-Element zugeordnet, das über einen Namen und einen Namespace verfügt.In the SOAP representation of a message contract, each header and body part maps to an XML element that has a name and a namespace.

Standardmäßig entspricht der Namespace dem Namespace des Dienstvertrags, an dem die Nachricht teilnimmt, und der Name wird durch den Membernamen festgelegt, auf den die Attribute MessageHeaderAttribute oder MessageBodyMemberAttribute angewandt wurden.By default, the namespace is the same as the namespace of the service contract that the message is participating in, and the name is determined by the member name to which the MessageHeaderAttribute or the MessageBodyMemberAttribute attributes are applied.

Die Standardeinstellungen können Sie ändern, indem Sie MessageContractMemberAttribute.Name und MessageContractMemberAttribute.Namespace bearbeiten (in der übergeordneten Klasse der Attribute MessageHeaderAttribute und MessageBodyMemberAttribute).You can change these defaults by manipulating the MessageContractMemberAttribute.Name and MessageContractMemberAttribute.Namespace (on the parent class of the MessageHeaderAttribute and MessageBodyMemberAttribute attributes).

Betrachten Sie die Klasse im folgenden Codebeispiel.Consider the class in the following code example.

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public Operation operation;  
  [MessageHeader(Namespace="http://schemas.contoso.com/auditing/2005")] public bool IsAudited;  
  [MessageBodyMember(Name="transactionData")] public BankingTransactionData theData;  
}  

In diesem Beispiel befindet sich der IsAudited-Header im Namespace, der vom Code festgelegt wird, und der Textteil, der den theData-Member darstellt, wird von einem XML-Element mit dem Namen transactionData abgebildet.In this example, the IsAudited header is in the namespace specified in the code, and the body part that represents the theData member is represented by an XML element with the name transactionData. Im Folgenden wird der XML-Code angezeigt, der für diesen Nachrichtenvertrag generiert wird.The following shows the XML generated for this message contract.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">  
  <s:Header>  
    <h:IsAudited xmlns:h="http://schemas.contoso.com/auditing/2005" xmlns="http://schemas.contoso.com/auditing/2005">false</h:IsAudited>  
    <h:operation xmlns:h="http://tempuri.org/" xmlns="http://tempuri.org/">Deposit</h:operation>  
  </s:Header>  
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
    <AuditedBankingTransaction xmlns="http://tempuri.org/">  
      <transactionData/>  
    </AuditedBankingTransaction>  
  </s:Body>  
</s:Envelope>  

Kontrolle, ob die SOAP-Textteile umbrochen werdenControlling Whether the SOAP Body Parts Are Wrapped

Standardmäßig sind die SOAP-Textteile in einem umbrochenen Element serialisiert.By default, the SOAP body parts are serialized inside a wrapped element. Beispielsweise zeigt der folgende Code das HelloGreetingMessage-Wrapperelement, das aus dem Namen des MessageContractAttribute-Typs im Nachrichtenvertrag für die HelloGreetingMessage-Nachricht generiert wird.For example, the following code shows the HelloGreetingMessage wrapper element generated from the name of the MessageContractAttribute type in the message contract for the HelloGreetingMessage message.

[MessageContract]
public class HelloGreetingMessage
{
  private string localGreeting;

  [MessageBodyMember(
    Name = "Salutations", 
    Namespace = "http://www.examples.com"
  )]
  public string Greeting
  {
    get { return localGreeting; }
    set { localGreeting = value; }
  }
}

/*
 The following is the request message, edited for clarity.
  
  <s:Envelope>
    <s:Header>
      <!-- Note: Some header content has been removed for clarity.
      <a:Action>http://GreetingMessage/Action</a:Action> 
      <a:To s:mustUnderstand="1"></a:To>
    </s:Header>
    <s:Body u:Id="_0" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <HelloGreetingMessage xmlns="Microsoft.WCF.Documentation">
        <Salutations xmlns="http://www.examples.com">Hello.</Salutations>
      </HelloGreetingMessage>
    </s:Body>
 </s:Envelope>
 */
  <MessageContract> _
  Public Class HelloGreetingMessage
	Private localGreeting As String

	<MessageBodyMember(Name := "Salutations", Namespace := "http://www.examples.com")> _
	Public Property Greeting() As String
	  Get
		  Return localGreeting
	  End Get
	  Set(ByVal value As String)
		  localGreeting = value
	  End Set
	End Property
  End Class

'  
'   The following is the request message, edited for clarity.
'    
'    <s:Envelope>
'      <s:Header>
'        <!-- Note: Some header content has been removed for clarity.
'        <a:Action>http://GreetingMessage/Action</a:Action> 
'        <a:To s:mustUnderstand="1"></a:To>
'      </s:Header>
'      <s:Body u:Id="_0" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
'        <HelloGreetingMessage xmlns="Microsoft.WCF.Documentation">
'          <Salutations xmlns="http://www.examples.com">Hello.</Salutations>
'      </s:Body>
'   </s:Envelope>
'   

Um das Wrapperelement zu unterdrücken, legen Sie die IsWrapped-Eigenschaft auf false fest.To suppress the wrapper element, set the IsWrapped property to false. Um den Namen und den Namespace des Wrapperelements zu kontrollieren, verwenden Sie die Eigenschaften WrapperName und WrapperNamespace.To control the name and the namespace of the wrapper element, use the WrapperName and WrapperNamespace properties.

Hinweis

Das Vorhandensein von mehr als einem Nachrichtentextteil in nicht umbrochenen Nachrichten ist nicht mit dem WS-I Basic Profile 1.1 kompatibel und wird bei der Gestaltung neuer Nachrichtenverträge nicht empfohlen.Having more than one message body part in messages that are not wrapped is not compliant with WS-I Basic Profile 1.1 and is not recommended when designing new message contracts. Allerdings kann es bei spezifischen Interoperabilitätsszenarien notwendig sein, mehr als einen nicht umbrochenen Nachrichtentextteil zu haben.However, it may be necessary to have more than one unwrapped message body part in certain specific interoperability scenarios. Wenn Sie mehrere Daten in einem Nachrichtentext übertragen möchten, wird die Verwendung des Standardumbruchmodus empfohlen.If you are going to transmit more than one piece of data in a message body, it is recommended to use the default (wrapped) mode. Mehr als einen Nachrichtenheader in nicht umbrochenen Nachrichten zu haben, ist vollkommen akzeptabel.Having more than one message header in unwrapped messages is completely acceptable.

Verwendung von benutzerdefinierten Typen innerhalb von NachrichtenverträgenUsing Custom Types Inside Message Contracts

Jeder einzelne Nachrichtenheader und Nachrichtentextteil wird mithilfe des ausgewählten Serialisierungsmoduls für den Dienstvertrag, bei dem die Nachricht verwendet wird, serialisiert (in XML konvertiert).Each individual message header and message body part is serialized (turned into XML) using the chosen serialization engine for the service contract where the message is used. Das Standardserialisierungsmodul, XmlFormatter, kann jeden Typ verarbeiten, der über einen Datenvertrag verfügt; entweder explizit (durch System.Runtime.Serialization.DataContractAttribute) oder implizit (bei einem primitiven Typ mit System.SerializableAttribute usw.).The default serialization engine, the XmlFormatter, can handle any type that has a data contract, either explicitly (by having the System.Runtime.Serialization.DataContractAttribute) or implicitly (by being a primitive type, having the System.SerializableAttribute, and so on). Weitere Informationen finden Sie unterFor more information, seeVerwenden von Datenverträgen. Using Data Contracts.

Im vorangehenden Beispiel müssen die Typen Operation und BankingTransactionData über einen Datenvertrag verfügen, und transactionDate ist serialisierbar, da DateTime primitiv ist (und über einen impliziten Datenvertrag verfügt).In the preceding example, the Operation and BankingTransactionData types must have a data contract, and transactionDate is serializable because DateTime is a primitive (and so has an implicit data contract).

Es ist jedoch möglich, zu einem anderen Serialisierungsmodul, dem XmlSerializer, umzuschalten.However, it is possible to switch to a different serialization engine, the XmlSerializer. Wenn Sie umschalten, sollten Sie sicherstellen, dass alle für die Nachrichtenheader und Textteile verwendeten Typen mithilfe des XmlSerializer serialisierbar sind.If you make such a switch, you should ensure that all of the types used for message headers and body parts are serializable using the XmlSerializer.

Verwendung von Arrays innerhalb von NachrichtenverträgenUsing Arrays Inside Message Contracts

Sie können Arrays von sich wiederholenden Elementen in Nachrichtenverträgen auf zwei Arten verwenden.You can use arrays of repeating elements in message contracts in two ways.

Auf der einen Seite können Sie ein MessageHeaderAttribute oder ein MessageBodyMemberAttribute direkt auf dem Array anwenden.The first is to use a MessageHeaderAttribute or a MessageBodyMemberAttribute directly on the array. In diesem Fall wird das gesamte Array als ein Element (d. h. ein Header und ein Textteil) mit mehreren Unterelementen serialisiert.In this case, the entire array is serialized as one element (that is, one header or one body part) with multiple child elements. Betrachten Sie die Klasse im folgenden Beispiel.Consider the class in the following example.

[MessageContract]  
public class BankingDepositLog  
{  
  [MessageHeader] public int numRecords;  
  [MessageHeader] public DepositRecord[] records;  
  [MessageHeader] public int branchID;  
}  

Das Ergebnis sind SOAP-Header, die den folgenden Beispielen ähneln.This results in SOAP headers is similar to the following.

<BankingDepositLog>  
<numRecords>3</numRecords>  
<records>  
  <DepositRecord>Record1</DepositRecord>  
  <DepositRecord>Record2</DepositRecord>  
  <DepositRecord>Record3</DepositRecord>  
</records>  
<branchID>20643</branchID>  
</BankingDepositLog>  

Eine Alternative besteht in der Verwendung des MessageHeaderArrayAttribute.An alternative to this is to use the MessageHeaderArrayAttribute. In diesem Fall wird jedes Arrayelement unabhängig serialisiert, wobei jedes Arrayelement über einen Header verfügt (ähnlich wie im folgenden Beispiel).In this case, each array element is serialized independently and so that each array element has one header, similar to the following.

<numRecords>3</numRecords>  
<records>Record1</records>  
<records>Record2</records>  
<records>Record3</records>  
<branchID>20643</branchID>  

Der Standardname für Arrayeinträge ist der Name des Members, auf den die MessageHeaderArrayAttribute-Attribute angewandt werden.The default name for array entries is the name of the member to which the MessageHeaderArrayAttribute attributes is applied.

Das MessageHeaderArrayAttribute-Attribut erbt von MessageHeaderAttribute.The MessageHeaderArrayAttribute attribute inherits from the MessageHeaderAttribute. Es verfügt über denselben Funktionssatz wie die Nicht-Arrayattribute. Beispielsweise ist es möglich, die Reihenfolge, den Namen und den Namespace für ein Array von Headern so einzurichten wie für einen Einzelheader.It has the same set of features as the non-array attributes, for example, it is possible to set the order, name, and namespace for an array of headers in the same way you set it for a single header. Wenn Sie die Order-Eigenschaft auf ein Array verwenden, gilt dies für das gesamte Array.When you use the Order property on an array, it applies to the entire array.

Sie können MessageHeaderArrayAttribute nur auf Arrays anwenden, nicht auf Sammlungen.You can apply the MessageHeaderArrayAttribute only to arrays, not collections.

Verwendung von Bytearrays in NachrichtenverträgenUsing Byte Arrays in Message Contracts

Bytearrays werden bei der Verwendung mit Nicht-Arrayattributen (MessageBodyMemberAttribute und MessageHeaderAttribute) nicht als Arrays behandelt, sondern als spezielle primitive Typen, die als Base64-codierte Daten in der resultierenden XML dargestellt werden.Byte arrays, when used with the non-array attributes (MessageBodyMemberAttribute and MessageHeaderAttribute), are not treated as arrays but as a special primitive type represented as Base64-encoded data in the resulting XML.

Wenn Sie Bytearrays mit dem Arrayattribut MessageHeaderArrayAttribute verwenden, hängen die Ergebnisse vom verwendeten Serialisierungsprogramm ab.When you use byte arrays with the array attribute MessageHeaderArrayAttribute, the results depend on the serializer in use. Mit dem Standardserialisierungsprogramm wird das Array als einzelner Eintrag für jedes Byte dargestellt.With the default serializer, the array is represented as an individual entry for each byte. Ist allerdings XmlSerializer ausgewählt (mithilfe von XmlSerializerFormatAttribute auf dem Dienstvertrag), werden Bytearrays als Base64-Daten behandelt, unabhängig davon, ob Array- oder Nicht-Arrayattribute verwendet werden.However, when the XmlSerializer is selected, (using the XmlSerializerFormatAttribute on the service contract), byte arrays are treated as Base64 data regardless of whether the array or non-array attributes are used.

Signieren und Verschlüsseln von Teilen der NachrichtSigning and Encrypting Parts of the Message

Ein Nachrichtenvertrag kann angeben, ob die Header und/oder der Text der Nachricht digital signiert und verschlüsselt werden soll.A message contract can indicate whether the headers and/or body of the message should be digitally signed and encrypted.

Dies wird erreicht, indem die MessageContractMemberAttribute.ProtectionLevel-Eigenschaften in den Attributen MessageHeaderAttribute und MessageBodyMemberAttribute festgelegt wird.This is done by setting the MessageContractMemberAttribute.ProtectionLevel property on the MessageHeaderAttribute and MessageBodyMemberAttribute attributes. Die Eigenschaft ist eine Enumeration des System.Net.Security.ProtectionLevel-Typs und kann auf None (keine Verschlüsselung oder Signatur), Sign (nur digitale Signatur) oder EncryptAndSign (sowohl Verschlüsselung als auch digitale Signatur) festgelegt werden.The property is an enumeration of the System.Net.Security.ProtectionLevel type and can be set to None (no encryption or signature), Sign (digital signature only), or EncryptAndSign (both encryption and a digital signature). Die Standardeinstellung ist EncryptAndSign.The default is EncryptAndSign.

Damit diese Sicherheitsfunktionen arbeiten, müssen Sie die Bindung und das Verhalten ordnungsgemäß konfigurieren.For these security features to work, you must properly configure the binding and behaviors. Wenn Sie diese Sicherheitsfunktionen ohne angemessene Konfiguration verwenden (beispielsweise der Versuch der Signierung einer Nachricht ohne Bereitstellung Ihrer Anmeldeinformationen), wird zum Validierungszeitpunkt eine Ausnahme ausgelöst.If you use these security features without the proper configuration (for example, attempting to sign a message without supplying your credentials), an exception is thrown at validation time.

Bei Nachrichtenheadern wird die Schutzebene für jeden Header einzeln festgelegt.For message headers, the protection level is determined individually for each header.

Für Nachrichtentextteile kann die Schutzebene als "minimale Schutzebene" angesehen werden.For message body parts, the protection level can be thought of as the "minimum protection level." Der Text verfügt jedoch unabhängig von der Anzahl der Textteile nur über eine Schutzebene.The body has only one protection level, regardless of the number of body parts. Die Schutzebene des Texts wird durch die höchste ProtectionLevel-Eigenschaftseinstellung aller Textteile bestimmt.The protection level of the body is determined by the highest ProtectionLevel property setting of all the body parts. Allerdings sollten Sie die Schutzebene eines jeden Textteils auf die tatsächlich erforderliche minimale Schutzebene festlegen.However, you should set the protection level of each body part to the actual minimum protection level required.

Betrachten Sie die Klasse im folgenden Codebeispiel.Consider the class in the following code example.

[MessageContract]  
public class PatientRecord  
{  
   [MessageHeader(ProtectionLevel=None)] public int recordID;  
   [MessageHeader(ProtectionLevel=Sign)] public string patientName;  
   [MessageHeader(ProtectionLevel=EncryptAndSign)] public string SSN;  
   [MessageBodyMember(ProtectionLevel=None)] public string comments;  
   [MessageBodyMember(ProtectionLevel=Sign)] public string diagnosis;  
   [MessageBodyMember(ProtectionLevel=EncryptAndSign)] public string medicalHistory;  
}  

In diesem Beispiel ist der recordID-Header nicht geschützt, patientName ist signed und SSN ist verschlüsselt und signiert.In this example, the recordID header is not protected, patientName is signed, and SSN is encrypted and signed. Auf mindestens einen Textteil, medicalHistory, wurde EncryptAndSign angewandt. Daher ist der gesamte Nachrichtentext verschlüsselt und signiert, auch wenn die Kommentare und Diagnosetextteile niedrigere Schutzebenen festlegen.At least one body part, medicalHistory, has EncryptAndSign applied, and thus the entire message body is encrypted and signed, even though the comments and diagnosis body parts specify lower protection levels.

SOAP-AktionSOAP Action

SOAP- und verwandte Webdienststandards definieren eine Eigenschaft mit dem Namen Action, die für jede gesendete SOAP-Nachricht vorhanden sein kann.SOAP and related Web services standards define a property called Action that can be present for every SOAP message sent. Die Eigenschaften OperationContractAttribute.Action und OperationContractAttribute.ReplyAction des Vorgangs kontrollieren den Wert dieser Eigenschaft.The operation's OperationContractAttribute.Action and OperationContractAttribute.ReplyAction properties control the value of this property.

SOAP-Header-AttributeSOAP Header Attributes

Der SOAP-Standard definiert die folgenden Attribute, die in einem Header verwendet werden können:The SOAP standard defines the following attributes that may exist on a header:

  • Actor/Role (Actor in SOAP 1.1, Role in SOAP 1.2)Actor/Role (Actor in SOAP 1.1, Role in SOAP 1.2)

  • MustUnderstand

  • Relay

Das Actor-Attribut oder das Role-Attribut legt den URI (Uniform Resource Identifier) des Knotens fest, für den ein bestimmter Header angegeben wurde.The Actor or Role attribute specifies the Uniform Resource Identifier (URI) of the node for which a given header is intended. Das MustUnderstand-Attribut gibt an, ob der Header die Knotenverarbeitung versteht.The MustUnderstand attribute specifies whether the node processing the header must understand it. Das Relay-Attribut gibt an, ob der Header an Downstreamknoten weitergeleitet werden soll.The Relay attribute specifies whether the header is to be relayed to downstream nodes. WCFWCF verarbeitet diese Attribute bei eingehenden Nachrichten nicht, mit Ausnahme des MustUnderstand-Attributs (wie weiter unten in diesem Thema im Abschnitt "Versionsvergabe für Nachrichtenverträge" angegeben). does not perform any processing of these attributes on incoming messages, except for the MustUnderstand attribute, as specified in the "Message Contract Versioning" section later in this topic. Allerdings wird es Ihnen ermöglicht, diese Attribute wie erforderlich zu lesen und zu schreiben (wie in der folgenden Beschreibung).However, it allows you to read and write these attributes as necessary, as in the following description.

Beim Versand einer Nachricht werden diese Attribute nicht standardmäßig ausgegeben.When sending a message, these attributes are not emitted by default. Sie können diese auf zwei Arten ändern:You can change this in two ways. Sie können die Attribute statisch auf einen gewünschten Wert festlegen, indem Sie die Eigenschaften MessageHeaderAttribute.Actor, MessageHeaderAttribute.MustUnderstand und MessageHeaderAttribute.Relay ändern (siehe folgendes Codebeispiel).First, you may statically set the attributes to any desired values by changing the MessageHeaderAttribute.Actor, MessageHeaderAttribute.MustUnderstand, and MessageHeaderAttribute.Relay properties, as shown in the following code example. (Beachten Sie, dass es keine Role-Eigenschaft gibt; die Einrichtung der Actor-Eigenschaft gibt das Role-Attribut aus, wenn Sie SOAP 1.2 verwenden).(Note that there is no Role property; setting the Actor property emits the Role attribute if you are using SOAP 1.2).

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader(Actor="http://auditingservice.contoso.com", MustUnderstand=true)] public bool IsAudited;  
  [MessageHeader] public Operation operation;  
  [MessageBodyMember] public BankingTransactionData theData;  
}  

Darüber hinaus können Sie diese Attribute dynamisch per Code kontrollieren.The second way to control these attributes is dynamically, through code. Dies können Sie erreichen, indem Sie den gewünschten Headertyp im MessageHeader<T>-Typ umschließen (nicht mit dem nichtgenerischen Typ zu verwechseln) und den Typ zusammen mit dem MessageHeaderAttribute verwenden.You can achieve this by wrapping the desired header type in the MessageHeader<T> type (be sure not to confuse this type with the non-generic version) and by using the type together with the MessageHeaderAttribute. Daraufhin können Sie die Eigenschaften auf MessageHeader<T> nutzen, um die SOAP-Attribute einzurichten (siehe folgendes Codebeispiel).Then, you can use properties on the MessageHeader<T> to set the SOAP attributes, as shown in the following code example.

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public MessageHeader<bool> IsAudited;  
  [MessageHeader] public Operation operation;  
  [MessageBodyMember] public BankingTransactionData theData;  
}  
// application code:  
BankingTransaction bt = new BankingTransaction();  
bt.IsAudited = new MessageHeader<bool>();  
bt.IsAudited.Content = false; // Set IsAudited header value to "false"  
bt.IsAudited.Actor="http://auditingservice.contoso.com";  
bt.IsAudited.MustUnderstand=true;  

Wenn Sie sowohl den dynamischen als auch den statischen Kontrollmechanismus verwenden, werden die statischen Einstellungen als Standard verwendet, wobei diese später allerdings mithilfe des dynamischen Mechanismus überschrieben werden können (siehe folgenden Code).If you use both the dynamic and the static control mechanisms, the static settings are used as a default but can later be overridden by using the dynamic mechanism, as shown in the following code.

[MessageHeader(MustUnderstand=true)] public MessageHeader<Person> documentApprover;  
// later on in the code:  
BankingTransaction bt = new BankingTransaction();  
bt.documentApprover = new MessageHeader<Person>();  
bt.documentApprover.MustUnderstand = false; // override the static default of 'true'  

Das Erstellen von wiederholten Headern mit einem dynamischen Attributsteuerelement ist zulässig (siehe folgenden Code).Creating repeated headers with dynamic attribute control is allowed, as shown in the following code.

[MessageHeaderArray] public MessageHeader<Person> documentApprovers[];  

Wenn Sie diese SOAP-Attribute auf Empfängerseite lesen möchten, muss die MessageHeader<T>-Klasse für den Header im Typ verwendet werden.On the receiving side, reading these SOAP attributes can only be done if the MessageHeader<T> class is used for the header in the type. Überprüfen Sie die Eigenschaften Actor, Relay oder MustUnderstand des Headers des MessageHeader<T>-Typs, um die Attributeinstellungen für die empfangene Nachricht anzuzeigen.Examine the Actor, Relay, or MustUnderstand properties of a header of the MessageHeader<T> type to discover the attribute settings on the received message.

Wenn eine Nachricht empfangen und dann zurückgesendet wird, werden die SOAP-Attributeinstellungen nur für Header des MessageHeader<T>-Typs wiederhergestellt.When a message is received and then sent back, the SOAP attribute settings only go round-trip for headers of the MessageHeader<T> type.

Reihenfolge von SOAP-TextteilenOrder of SOAP Body Parts

In einigen Fällen müssen Sie die Reihenfolge der Textteile kontrollieren.In some circumstances, you may need to control the order of the body parts. Die Reihenfolge der Textelemente ist standardmäßig alphabetisch, kann aber über die MessageBodyMemberAttribute.Order-Eigenschaft gesteuert werden.The order of the body elements is alphabetical by default, but can be controlled by the MessageBodyMemberAttribute.Order property. Diese Eigenschaft verfügt über dieselbe Semantik wie die Eigenschaft DataMemberAttribute.Order, abgesehen vom Verhalten im Vererbungsszenario (in Nachrichtenverträgen werden Textmember vom Basistyp nicht vor den Textmembern des abgeleiteten Typs sortiert).This property has the same semantics as the DataMemberAttribute.Order property, except for the behavior in inheritance scenarios (in message contracts, base type body members are not sorted before the derived type body members). Weitere Informationen finden Sie unterFor more information, seeDatenmemberreihenfolge. Data Member Order.

Im folgenden Beispiel käme amount normalerweise zuerst, da es alphabetisch an erster Stelle steht.In the following example, amount would normally come first because it is first alphabetically. Die Order-Eigenschaft setzt es jedoch an die dritte Position.However, the Order property puts it into the third position.

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public Operation operation;  
  [MessageBodyMember(Order=1)] public Account sourceAccount;  
  [MessageBodyMember(Order=2)] public Account targetAccount;  
  [MessageBodyMember(Order=3)] public int amount;  
}  

Versionsverwaltung für NachrichtenverträgeMessage Contract Versioning

Sie müssen möglicherweise gelegentlich Nachrichtenverträge ändern.Occasionally, you may need to change message contracts. Beispielsweise kann eine neue Version Ihrer Anwendung einen zusätzlichen Header zu einer Nachricht hinzufügen.For example, a new version of your application may add an extra header to a message. Erfolgt dann ein Versand von der neuen Version zur alten, muss das System den zusätzlichen Header und einen fehlenden Header (in der anderen Richtung) verarbeiten.Then, when sending from the new version to the old, the system must deal with an extra header, as well as a missing header when going in the other direction.

Für Versionsheader gelten die folgenden Regeln:The following rules apply for versioning headers:

  • WCFWCF widersetzt sich dem fehlenden Header nicht. Die entsprechenden Member behalten Ihre Standardwerte. does not object to the missing headers—the corresponding members are left at their default values.

  • WCFWCF ignoriert auch unerwartete zusätzliche Header. also ignores unexpected extra headers. Die Ausnahme zu dieser Regel besteht darin, dass der zusätzliche Header über ein MustUnderstand-Attribut verfügt, das in der eingehenden SOAP-Nachricht auf true festgelegt ist – in diesem Fall wird eine Ausnahme ausgelöst, da ein Header, der verstanden werden muss, nicht verarbeitet werden kann.The one exception to this rule is if the extra header has a MustUnderstand attribute set to true in the incoming SOAP message—in this case, an exception is thrown because a header that must be understood cannot be processed.

Nachrichtentexte haben ähnliche Versionsregeln – sowohl fehlende als auch zusätzliche Nachrichtentextteile werden ignoriert.Message bodies have similar versioning rules—both missing and additional message body parts are ignored.

Überlegungen zur VererbungInheritance Considerations

Ein Nachrichtenvertragstyp kann von einem anderen Typ erben, solange der Basistyp ebenfalls über einen Nachrichtenvertrag verfügt.A message contract type can inherit from another type, as long as the base type also has a message contract.

Bei der Erstellung einer Nachricht oder beim Zugriff darauf mithilfe eines Nachrichtenvertragstyps, der von anderen Nachrichtenvertragstypen erbt, gelten die folgenden Regeln.When creating or accessing a message using a message contract type that inherits from other message contract types, the following rules apply:

  • Alle Nachrichtenheader in der Vererbungshierarchie werden gesammelt, um den vollständigen Satz an Headern für die Nachricht zu bilden.All of the message headers in the inheritance hierarchy are collected together to form the full set of headers for the message.

  • Alle Nachrichtentextteile in der Vererbungshierarchie werden gesammelt, um den vollständigen Nachrichtentext zu bilden.All of the message body parts in the inheritance hierarchy are collected together to form the full message body. Die Textteile werden basierend auf den üblichen Sortierungsregeln sortiert (nach der MessageBodyMemberAttribute.Order-Eigenschaft und danach alphabetisch), wobei die Position in der Vererbungshierarchie unbeachtet bleibt.The body parts are ordered according to the usual ordering rules (by MessageBodyMemberAttribute.Order property and then alphabetical), with no relevance to their place in the inheritance hierarchy. Wenn Nachrichtentextteile in mehreren Ebenen der Vererbungsstruktur auftauchen, wird von der Verwendung der Nachrichtenvertragsvererbung strengstens abgeraten.Using message contract inheritance where message body parts occur at multiple levels of the inheritance tree is strongly discouraged. Wenn eine Basisklasse und eine abgeleitete Klasse einen Header oder einen Textteil mit demselben Namen definieren, wird der Member der Basisklasse verwendet, um den Wert des Headers oder des Textteils zu speichern.If a base class and a derived class define a header or a body part with the same name, the member from the base-most class is used to store the value of that header or body part.

Betrachten Sie die Klassen im folgenden Codebeispiel.Consider the classes in the following code example.

[MessageContract]  
public class PersonRecord  
{  
  [MessageHeader(Name="ID")] public int personID;  
  [MessageBodyMember] public string patientName;  
}  

[MessageContract]  
public class PatientRecord : PersonRecord  
{  
  [MessageHeader(Name="ID")] public int patientID;  
  [MessageBodyMember] public string diagnosis;  
}  

Die PatientRecord-Klasse beschreibt eine Nachricht mit einem Header mit dem Namen ID.The PatientRecord class describes a message with one header called ID. Der Header entspricht der personID und nicht dem patientID-Member, da der Basismember ausgewählt wird.The header corresponds to the personID and not the patientID member, because the base-most member is chosen. Somit ist das patientID-Feld in diesem Fall unbrauchbar.Thus, the patientID field is useless in this case. Der Text der Nachricht enthält das diagnosis-Element, gefolgt vom patientName-Element, da dies die alphabetische Reihenfolge ist.The body of the message contains the diagnosis element followed by the patientName element, because that is the alphabetical order. Beachten Sie, dass das Beispiel ein Muster zeigt, von dem strengstens abgeraten wird: sowohl der Basisklassenvertrag als auch der abgeleitete Klassenvertrag verfügen über Nachrichtentextteile.Notice that the example shows a pattern that is strongly discouraged: both the base and the derived message contracts have message body parts.

Überlegungen zu WSDLWSDL Considerations

Bei der Erstellung eines WSDL (Web Services Description Language)-Vertrags aus einem Dienst, der Nachrichtenverträge nutzt, ist es wichtig, daran zu denken, dass nicht alle Nachrichtenvertragsfunktionen in der resultierenden WSDL widergespiegelt werden.When generating a Web Services Description Language (WSDL) contract from a service that uses message contracts, it is important to remember that not all message contract features are reflected in the resulting WSDL. Berücksichtigen Sie die folgenden Punkte:Consider the following points:

  • WSDL kann den Begriff eines Arrays aus Headern nicht ausdrücken.WSDL cannot express the concept of an array of headers. Bei der Erstellung von Nachrichten mit einem Array aus Headern mithilfe des MessageHeaderArrayAttribute spiegelt die resultierende WSDL nur einen Header wider anstelle eines Array.When creating messages with an array of headers using the MessageHeaderArrayAttribute, the resulting WSDL reflects only one header instead of the array.

  • Das resultierende WSDL-Dokument spiegelt möglicherweise einige der Informationen auf Schutzebene nicht wider.The resulting WSDL document may not reflect some protection-level information.

  • Der in der WSDL generierte Nachrichtentyp verfügt über denselben Namen wie die Klasse des Nachrichtenvertragstyps.The message type generated in the WSDL has the same name as the class name of the message contract type.

  • Bei Verwendung desselben Nachrichtenvertrags in mehreren Vorgängen werden mehrere Nachrichtentypen im WSDL-Dokument generiert.When using the same message contract in multiple operations, multiple message types are generated in the WSDL document. Die Namen werden durch Hinzufügen der Zahlen "2", "3" usw. für eine aufeinanderfolgende Verwendung eindeutig gekennzeichnet.The names are made unique by adding the numbers "2", "3", and so on, for subsequent uses. Beim Rückimport der WSDL werden mehrere Nachrichtenvertragstypen erstellt, die abgesehen von ihren Namen identisch sind.When importing back the WSDL, multiple message contract types are created and are identical except for their names.

Überlegungen zur SOAP-CodierungSOAP Encoding Considerations

WCFWCF ermöglicht es Ihnen, das ältere SOAP-Codierungsformat für XML zu verwenden. Allerdings wird dies nicht empfohlen. allows you to use the legacy SOAP encoding style of XML, however, its use is not recommended. Bei der Verwendung dieses Formats (durch Festlegen der Use-Eigenschaft auf Encoded auf dem System.ServiceModel.XmlSerializerFormatAttribute, das auf den Dienstvertrag angewandt wird), gelten die folgenden zusätzlichen Überlegungen:When using this style (by setting the Use property to Encoded on the System.ServiceModel.XmlSerializerFormatAttribute applied to the service contract), the following additional considerations apply:

  • Die Nachrichtenheader werden nicht unterstützt. Dies bedeutet, dass das Attribut MessageHeaderAttribute und das Arrayattribut MessageHeaderArrayAttribute nicht mit der SOAP-Codierung kompatibel sind.The message headers are not supported; this means that the attribute MessageHeaderAttribute and the array attribute MessageHeaderArrayAttribute are incompatible with SOAP encoding.

  • Wird der Nachrichtenvertrag nicht umbrochen, d. h., ist die Eigenschaft IsWrapped auf false festgelegt, kann der Nachrichtenvertrag nur über einen Textteil verfügen.If the message contract is not wrapped, that is, if the property IsWrapped is set to false, the message contract can have only one body part.

  • Der Name des Wrapperelements für den Anforderungsnachrichtenvertrag muss zum Vorgangsnamen passen.The name of the wrapper element for the request message contract must match the operation name. Verwenden Sie hierfür die WrapperName-Eigenschaft des Nachrichtenvertrags.Use the WrapperName property of the message contract for this.

  • Der Name des Wrapperelements für den Antwortnachrichtenvertrag muss dem Namen des Vorgangs entsprechen, der über das Suffix "Response" verfügt.The name of the wrapper element for the response message contract must be the same as the name of the operation suffixed by 'Response'. Verwenden Sie hierfür die WrapperName-Eigenschaft des Nachrichtenvertrags.Use the WrapperName property of the message contract for this.

  • SOAP-Codierung behält Objektverweise bei.SOAP encoding preserves object references. Betrachten Sie hierzu den folgenden Beispielcode:For example, consider the following code.

    [MessageContract(WrapperName="updateChangeRecord")]  
    public class ChangeRecordRequest  
    {  
      [MessageBodyMember] Person changedBy;  
      [MessageBodyMember] Person changedFrom;  
      [MessageBodyMember] Person changedTo;  
    }  
    
    [MessageContract(WrapperName="updateChangeRecordResponse")]  
    public class ChangeRecordResponse  
    {  
      [MessageBodyMember] Person changedBy;  
      [MessageBodyMember] Person changedFrom;  
      [MessageBodyMember] Person changedTo;  
    }  
    
    // application code:  
    ChangeRecordRequest cr = new ChangeRecordRequest();  
    Person p = new Person("John Doe");  
    cr.changedBy=p;  
    cr.changedFrom=p;  
    cr.changedTo=p;  
    

Nach der Serialisierung der Nachricht mithilfe von SOAP-Codierung enthalten changedFrom und changedTo nicht ihre eigenen Kopien von p, sondern verweisen auf die Kopie innerhalb des changedBy-Elements.After serializing the message using SOAP encoding, changedFrom and changedTo do not contain their own copies of p, but instead point to the copy inside the changedBy element.

Überlegungen zur LeistungPerformance Considerations

Jeder Nachrichtenheader und jeder Nachrichtentextteil wird unabhängig von den anderen serialisiert.Every message header and message body part is serialized independently of the others. Deshalb können die gleichen Namespaces wieder für jeden Header und jeden Textteil deklariert werden.Therefore, the same namespaces can be declared again for each header and body part. Zur Verbesserung der Leistung, insbesondere in Bezug auf die Größe der zu übertragenden Nachricht, fassen Sie mehrere Header und Textteile in einem einzelnen Header oder einzelnen Textteil zusammen.To improve performance, especially in terms of the size of the message on the wire, consolidate multiple headers and body parts into a single header or body part. Beispielsweise anstelle des folgenden Codes:For example, instead of the following code:

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public Operation operation;  
  [MessageBodyMember] public Account sourceAccount;  
  [MessageBodyMember] public Account targetAccount;  
  [MessageBodyMember] public int amount;  
}  

Verwenden Sie diesen Code.Use this code.

[MessageContract]  
public class BankingTransaction  
{  
  [MessageHeader] public Operation operation;  
  [MessageBodyMember] public OperationDetails details;  
}  

[DataContract]  
public class OperationDetails  
{  
  [DataMember] public Account sourceAccount;  
  [DataMember] public Account targetAccount;  
  [DataMember] public int amount;  
}  

Ereignisbasiertes asynchrones Modell und NachrichtenverträgeEvent-based Asynchronous and Message Contracts

Die Entwurfsrichtlinien für das ereignisbasierte asynchrone Modell besagen, dass in den Fällen, in denen mehr als ein Wert zurückgegeben wird, ein Wert in der Result-Eigenschaft und die übrigen Werte in Eigenschaften des EventArgs-Objekts zurückgegeben werden sollen.The design guidelines for the event-based asynchronous model state that if more than one value is returned, one value is returned as the Result property and the others are returned as properties on the EventArgs object. Wenn ein Client Metadaten mithilfe der ereignisbasierten asynchronen Befehlsoptionen importiert, und der Vorgang mehr als einen Wert zurückgibt, dann gibt das EventArgs-Standardobjekt infolgedessen einen Wert in der Result-Eigenschaft zurück, während die übrigen Werte in Eigenschaften des EventArgs-Objekts zurückgegeben werden.One result of this is that if a client imports metadata using the event-based asynchronous command options and the operation returns more than one value, the default EventArgs object returns one value as the Result property and the remainder are properties of the EventArgs object.

Wenn das Nachrichtenobjekt in der Result-Eigenschaft und die Rückgabewerte als Eigenschaften dieses Objekts übermittelt werden sollen, verwenden Sie die Befehlsoption /messageContract.If you want to receive the message object as the Result property and have the returned values as properties on that object, use the /messageContract command option. Damit wird eine Signatur generiert, bei der die Antwortnachricht in der Result-Eigenschaft des EventArgs-Objekts zurückgegeben wird.This generates a signature that returns the response message as the Result property on the EventArgs object. Alle internen Rückgabewerte sind dann Eigenschaften des Antwortnachrichtenobjekts.All internal return values are then properties of the response message object.

Siehe auchSee Also

Verwenden von DatenverträgenUsing Data Contracts
Entwerfen und Implementieren von DienstenDesigning and Implementing Services