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

Windows Communication Foundation (WCF) kann als Messaginginfrastruktur betrachtet werden.The Windows Communication Foundation (WCF) can be thought of as a messaging infrastructure. Dienstvorgänge können Nachrichten empfangen, sie verarbeiten und ihnen Nachrichten schicken.Service operations can receive messages, process them, and send them messages. Nachrichten werden mit Vorgangsverträgen beschrieben.Messages are described using operation contracts. Beispiel:For example, consider the following contract.

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    float GetAirfare(string fromCity, string toCity);  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  

    <OperationContract()>  
    Function GetAirfare(fromCity As String, toCity As String) As Double  
End Interface  

Hier akzeptiert der GetAirfare-Vorgang eine Nachricht mit Informationen über fromCity und toCity und gibt dann eine Nachricht zurück, die eine Zahl enthält.Here, the GetAirfare operation accepts a message with information about fromCity and toCity, and then returns a message that contains a number.

In diesem Thema werden die verschiedenen Möglichkeiten erläutert, wie ein Vorgangsvertrag Nachrichten beschreiben kann.This topic explains the various ways in which an operation contract can describe messages.

Beschreiben von Nachrichten mithilfe von ParameternDescribing Messages by Using Parameters

Die einfachste Art zur Beschreibung einer Nachricht ist die Verwendung einer Parameterliste und des Rückgabewerts.The simplest way to describe a message is to use a parameter list and the return value. Im vorherigen Beispiel wurden der fromCity- und der toCity-Zeichenfolgenparameter zur Beschreibung der Anforderungsnachricht verwendet, und der Gleitkommarückgabewert wurde zur Beschreibung der Antwortnachricht verwendet.In the preceding example, the fromCity and toCity string parameters were used to describe the request message, and the float return value was used to describe the reply message. Wenn der Rückgabewert allein zur Beschreibung einer Antwortnachricht nicht ausreicht, können out-Parameter verwendet werden.If the return value alone is not enough to describe a reply message, out parameters may be used. Der folgende Vorgang enthält z. B. fromCity und toCity in der Anforderungsnachricht und eine Zahl zusammen mit einer Währung in der Antwortnachricht:For example, the following operation has fromCity and toCity in its request message, and a number together with a currency in its reply message:

[OperationContract]  
float GetAirfare(string fromCity, string toCity, out string currency);  
<OperationContract()>  
    Function GetAirfare(fromCity As String, toCity As String) As Double  

Sie können zusätzlich Verweisparameter verwenden, um einen Parameter sowohl zu einem Teil der Anforderungs- als auch der Antwortnachricht zu machen.Additionally, you may use reference parameters to make a parameter part of both the request and the reply message. Die Parameter müssen Typen angehören, die serialisiert (zu XML konvertiert) werden können.The parameters must be of types that can be serialized (converted to XML). WCF verwendet standardmäßig eine Komponente mit dem Namen der DataContractSerializer Klasse zum Ausführen dieser Konvertierung.By default, WCF uses a component called the DataContractSerializer class to perform this conversion. Die meisten primitiven Typen (z. B. int, string, float und DateTime) werden unterstützt.Most primitive types (such as int, string, float, and DateTime.) are supported. Benutzerdefinierte Typen müssen normalerweise einen Datenvertrag aufweisen.User-defined types must normally have a data contract. Weitere Informationen finden Sie unter mithilfe von Datenverträgen.For more information, see Using Data Contracts.

public interface IAirfareQuoteService  
{  
    [OperationContract]  
    float GetAirfare(Itinerary itinerary, DateTime date);  

    [DataContract]  
    public class Itinerary  
    {  
        [DataMember]  
        public string fromCity;  
        [DataMember]  
        public string toCity;  
   }  
}  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    GetAirfare(itinerary as Itinerary, date as DateTime) as Double  

    <DataContract()>  
    Class Itinerary  

        <DataMember()>  
        Public fromCity As String  
        <DataMember()>  
        Public toCity As String  
    End Class  
End Interface  

Gelegentlich ist der DataContractSerializer nicht zur Serialisierung der Typen geeignet.Occasionally, the DataContractSerializer is not adequate to serialize your types. WCF unterstützt ein alternatives Serialisierungsmodul, das XmlSerializer, die Sie auch zur Serialisierung von Parametern verwenden können.WCF supports an alternative serialization engine, the XmlSerializer, which you can also use to serialize parameters. Das XmlSerializer bietet mehr Kontrolle über den resultierenden XML-Code durch Verwendung von Attributen, wie z. B. XmlAttributeAttribute.The XmlSerializer allows you to use more control over the resultant XML using attributes such as the XmlAttributeAttribute. Um zur Verwendung von XmlSerializer für einen bestimmten Vorgang oder den gesamten Dienst überzugehen, wenden Sie das XmlSerializerFormatAttribute-Attribut auf einen Vorgang oder einen Dienst an.To switch to using the XmlSerializer for a particular operation or for the entire service, apply the XmlSerializerFormatAttribute attribute to an operation or a service. Zum Beispiel:For example:

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    [XmlSerializerFormat]  
    float GetAirfare(Itinerary itinerary, DateTime date);  
}  
public class Itinerary  
{  
    public string fromCity;  
    public string toCity;  
    [XmlAttribute]  
    public bool isFirstClass;  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    <XmlSerializerFormat>  
    GetAirfare(itinerary as Itinerary, date as DateTime) as Double  

End Interface  

Class Itinerary  

    Public fromCity As String  
    Public toCity As String  
    <XmlSerializerFormat()>  
    Public isFirstClass As Boolean  
End Class  

Weitere Informationen finden Sie unter verwenden der XmlSerializer-Klasse.For more information, see Using the XmlSerializer Class. Vergessen Sie nicht, dass ein manueller Wechsel zum XmlSerializer, wie hier dargestellt, nicht empfohlen wird, wenn nicht triftige Gründe dafür vorliegen, wie sie in diesem Thema ausführlich beschrieben werden.Remember that manually switching to the XmlSerializer as shown here is not recommended unless you have specific reasons to do so as detailed in that topic.

Zur Isolierung von .NET-Parameternamen von Vertragsnamen können Sie das MessageParameterAttribute-Attribut verwenden. Verwenden Sie die Name-Eigenschaft zur Festlegung des Vertragsnamens.To isolate .NET parameter names from contract names, you can use the MessageParameterAttribute attribute, and use the Name property to set the contract name. Der folgende Vorgangsvertrag entspricht z. B. dem ersten Beispiel in diesem Thema.For example, the following operation contract is equivalent to the first example in this topic.

[OperationContract]  
public float GetAirfare(  
    [MessageParameter(Name="fromCity")] string originCity,  
    [MessageParameter(Name="toCity")] string destinationCity);  
<OperationContract()>  
  Function GetAirfare(<MessageParameter(Name := "fromCity")> fromCity As String, <MessageParameter(Name := "toCity")> toCity As String) As Double  

Beschreiben von leeren NachrichtenDescribing Empty Messages

Eine leere Anforderungsnachricht kann dadurch beschrieben werden, dass sie keine Eingabe- oder Verweisparameter aufweist.An empty request message can be described by having no input or reference parameters. Beispiel in C#:For example in C#:

[OperationContract]

public int GetCurrentTemperature();

Beispiel in VB:For example in VB:

<OperationContract()>

Function GetCurrentTemperature() as Integer

Eine leere Antwortnachricht kann dadurch beschrieben werden, dass sie einen void-Rückgabetyp und keine Ausgabe- oder Verweisparameter aufweist.An empty reply message can be described by having a void return type and no output or reference parameters. Beispiel:For example in:

[OperationContract]  
public void SetTemperature(int temperature);  
<OperationContract()>  
Sub SetTemperature(temperature As Integer)  

Dies unterscheidet sich von einem unidirektionalen Vorgang wie z. B.:This is different from a one-way operation, such as:

[OperationContract(IsOneWay=true)]  
public void SetLightbulbStatus(bool isOn);  
<OperationContract(IsOneWay:=True)>  
Sub SetLightbulbStatus(isOne As Boolean)  

Der SetTemperatureStatus-Vorgang gibt eine leere Nachricht zurück.The SetTemperatureStatus operation returns an empty message. Er gibt stattdessen möglicherweise einen Fehler zurück, wenn es ein Problem beim Verarbeiten der Eingabenachricht gibt.It may return a fault instead if there is a problem processing the input message. Der SetLightbulbStatus-Vorgang gibt keinen Wert zurück.The SetLightbulbStatus operation returns nothing. Es gibt keine Möglichkeit, eine Fehlerbedingung dieses Vorgangs zu übermitteln.There is no way to communicate a fault condition from this operation.

Beschreiben von Nachrichten mithilfe von NachrichtenverträgenDescribing Messages by Using Message Contracts

Sie können einen einzelnen Typ verwenden, um die ganze Nachricht darzustellen.You may want to use a single type to represent the entire message. Es ist zwar möglich, für diesen Zweck einen Datenvertrag zu verwenden, empfohlen wird jedoch die Verwendung eines Nachrichtenvertrags – dadurch werden unnötige Wrappingebenen im resultierenden XML-Code vermieden.While it is possible to use a data contract for this purpose, the recommended way to do this is to use a message contract—this avoids unnecessary levels of wrapping in the resultant XML. Darüber hinaus ermöglichen Nachrichtenverträge eine bessere Kontrolle über die resultierenden Nachrichten.Additionally, message contracts allow you to exercise more control over resultant messages. Sie können z. B. entscheiden, welche Informationen im Nachrichtentext und welche in den Nachrichtenheadern enthalten sein sollen.For instance, you can decide which pieces of information should be in the message body and which should be in the message headers. Im folgenden Beispiel wird die Verwendung von Nachrichtenverträgen veranschaulicht.The following example shows the use of message contracts.

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    GetAirfareResponse GetAirfare(GetAirfareRequest request);  
}  

[MessageContract]  
public class GetAirfareRequest  
{  
    [MessageHeader] public DateTime date;  
    [MessageBodyMember] public Itinerary itinerary;  
}  

[MessageContract]  
public class GetAirfareResponse  
{  
    [MessageBodyMember] public float airfare;  
    [MessageBodyMember] public string currency;  
}  

[DataContract]  
public class Itinerary  
{  
    [DataMember] public string fromCity;  
    [DataMember] public string toCity;  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    Function GetAirfare(request As GetAirfareRequest) As GetAirfareResponse  
End Interface  

<MessageContract()>  
Public Class GetAirfareRequest  
    <MessageHeader()>   
    Public Property date as DateTime  
    <MessageBodyMember()>  
    Public Property itinerary As Itinerary  
End Class  

<MessageContract()>  
Public Class GetAirfareResponse  
    <MessageBodyMember()>  
    Public Property airfare As Double  
    <MessageBodyMember()> Public Property currency As String  
End Class  

<DataContract()>  
Public Class Itinerary  
    <DataMember()> Public Property fromCity As String  
    <DataMember()> Public Property toCity As String  
End Class  

Weitere Informationen finden Sie unter Verwendung von Nachrichtenverträgen.For more information, see Using Message Contracts.

Im vorigen Beispiel wird die DataContractSerializer-Klasse noch standardmäßig verwendet.In the previous example, the DataContractSerializer class is still used by default. Die XmlSerializer-Klasse kann auch in Verbindung mit Nachrichtenverträgen verwendet werden.The XmlSerializer class can also be used with message contracts. Zu diesem Zweck wenden Sie das XmlSerializerFormatAttribute-Attribut entweder auf den Vorgang oder auf den Vertrag an, und verwenden Sie Typen, die mit der XmlSerializer-Klasse in den Nachrichtenheadern und Textmembern kompatibel sind.To do this, apply the XmlSerializerFormatAttribute attribute to either the operation or the contract, and use types compatible with the XmlSerializer class in the message headers and body members.

Beschreiben von Nachrichten mithilfe von StreamsDescribing Messages by Using Streams

Eine andere Möglichkeit zur Beschreibung von Nachrichten in Vorgängen ist die Verwendung der Stream-Klasse oder einer der von ihr abgeleiteten Klasse in einem Vorgangsvertrag oder als Textmember eines Nachrichtenvertrags (es muss sich in diesem Fall um den einzigen Member handeln).Another way to describe messages in operations is to use the Stream class or one of its derived classes in an operation contract or as a message contract body member (it must be the only member in this case). Für eingehende Nachrichten muss der Typ Stream sein – es können keine abgeleiteten Klassen verwendet werden.For incoming messages, the type must be Stream—you cannot use derived classes.

Statt das Serialisierungsprogramm aufzurufen, WCF Ruft Daten aus einem Stream und setzt sie direkt in eine ausgehende Nachricht oder ruft Daten aus einer eingehenden Nachricht ab und setzt sie direkt in einen Stream.Instead of invoking the serializer, WCF retrieves data from a stream and puts it directly into an outgoing message, or retrieves data from an incoming message and puts it directly into a stream. Im folgenden Beispiel wird die Verwendung von Streams veranschaulicht.The following sample shows the use of streams.

[OperationContract]  
public Stream DownloadFile(string fileName);  
<OperationContract()>  
Function DownloadFile(fileName As String) As String  

Sie können Stream- und Nicht-Stream-Daten in einem einzelnen Nachrichtentext nicht kombinieren.You cannot combine Stream and non-stream data in a single message body. Verwenden Sie einen Nachrichtenvertrag, um die zusätzlichen Daten in Nachrichtenheader einzusetzen.Use a message contract to put the extra data in message headers. Im folgenden Beispiel wird die falsche Verwendung von Streams bei der Definition des Vorgangsvertrags veranschaulicht.The following example shows the incorrect usage of streams when defining the operation contract.

//Incorrect:  
// [OperationContract]  
// public void UploadFile (string fileName, Stream fileData);  
'Incorrect:  
    '<OperationContract()>  
    Public Sub UploadFile(fileName As String, fileData As StreamingContext)  

Im folgenden Beispiel wird die korrekte Verwendung von Streams bei der Definition eines Vorgangsvertrags veranschaulicht.The following sample shows the correct usage of streams when defining an operation contract.

[OperationContract]  
public void UploadFile (UploadFileMessage message);  
//code omitted  
[MessageContract]  
public class UploadFileMessage  
{  
    [MessageHeader] public string fileName;  
    [MessageBodyMember] public Stream fileData;  
}  
<OperationContract()>  
Public Sub UploadFile(fileName As String, fileData As StreamingContext)  
'Code Omitted  
<MessageContract()>  
Public Class UploadFileMessage  
   <MessageHeader()>  
    Public Property fileName As String  
    <MessageBodyMember()>  
    Public Property fileData As Stream  
End Class  

Weitere Informationen finden Sie unter umfangreiche Daten und Streaming.For more information, see Large Data and Streaming.

Verwenden der Message-KlasseUsing the Message Class

Um umfassende programmgesteuerte Kontrolle über gesendete oder empfangene Nachrichten zu haben, können Sie die Message-Klasse direkt verwenden, wie im folgenden Beispielcode dargestellt wird.To have complete programmatic control over messages sent or received, you can use the Message class directly, as shown in the following example code.

[OperationContract]  
public void LogMessage(Message m);  
<OperationContract()>  
Sub LogMessage(m As Message)  

Dies ist eine erweiterte-remotezugriffsszenario, das ausführlich beschrieben wird verwenden der Meldungsklasse.This is an advanced scenario, which is described in detail in Using the Message Class.

Beschreiben von FehlernachrichtenDescribing Fault Messages

Zusätzlich zu den Nachrichten, die durch den Rückgabewert und Ausgabe- oder Verweisparameter beschrieben werden, kann jeder nicht unidirektionale Vorgang mindestes zwei mögliche Nachrichten zurückgeben: die normale Antwortnachricht und eine Fehlernachricht.In addition to the messages that are described by the return value and output or reference parameters, any operation that is not one-way can return at least two possible messages: its normal response message and a fault message. Betrachten Sie den folgenden Vorgangsvertrag.Consider the following operation contract.

[OperationContract]  
float GetAirfare(string fromCity, string toCity, DateTime date);  
<OperationContract()>  
Function GetAirfare(fromCity As String, toCity As String, date as DateTime)  

Dieser Vorgang kann entweder eine normale Nachricht zurückgeben, die eine float-Zahl enthält, oder eine Fehlernachricht, die einen Fehlercode und eine Beschreibung enthält.This operation may either return a normal message that contains a float number, or a fault message that contains a fault code and a description. Dies kann durch Auslösen einer FaultException in der Dienstimplementierung erreicht werden.You can accomplish this by throwing a FaultException in your service implementation.

Sie können weitere mögliche Fehlermeldungen angeben, indem Sie das FaultContractAttribute-Attribut verwenden.You can specify additional possible fault messages by using the FaultContractAttribute attribute. Die zusätzlichen Fehler müssen mit dem DataContractSerializer serialisierbar sein, wie im folgenden Beispielcode gezeigt.The additional faults must be serializable using the DataContractSerializer, as shown in the following example code.

[OperationContract]  
[FaultContract(typeof(ItineraryNotAvailableFault))]  
float GetAirfare(string fromCity, string toCity, DateTime date);  

//code omitted  

[DataContract]  
public class ItineraryNotAvailableFault  
{  
    [DataMember]  
    public bool IsAlternativeDateAvailable;  

    [DataMember]  
    public DateTime alternativeSuggestedDate;  
}  
<OperationContract()>  
<FaultContract(GetType(ItineraryNotAvailableFault))>  
Function GetAirfare(fromCity As String, toCity As String, date as DateTime) As Double  

'Code Omitted  
<DataContract()>  
Public Class  
  <DataMember()>  
  Public Property IsAlternativeDateAvailable As Boolean  
  <DataMember()>  
  Public Property alternativeSuggestedDate As DateTime  
End Class  

Diese zusätzlichen Fehler können durch Auslösen einer FaultException<TDetail> des geeigneten Datenvertragstyps generiert werden.These additional faults can be generated by throwing a FaultException<TDetail> of the appropriate data contract type. Weitere Informationen finden Sie unter Behandlung von Ausnahmen und Fehlern.For more information, see Handling Exceptions and Faults.

Sie können die XmlSerializer-Klasse nicht verwenden, um Fehler zu beschreiben.You cannot use the XmlSerializer class to describe faults. Das XmlSerializerFormatAttribute hat keine Auswirkungen auf Fehlerverträge.The XmlSerializerFormatAttribute has no effect on fault contracts.

Verwenden von abgeleiteten TypenUsing Derived Types

Sie können einen Basistyp für einen Vorgangs- oder Nachrichtenvertrag verwenden und dann einen abgeleiteten Typ verwenden, wenn Sie den Vorgang tatsächlich aufrufen.You may want to use a base type in an operation or a message contract, and then use a derived type when actually invoking the operation. In diesem Fall müssen Sie entweder das ServiceKnownTypeAttribute-Attribut oder einen alternativen Mechanismus verwenden, um die Verwendung von abgeleiteten Typen zu ermöglichen.In this case, you must use either the ServiceKnownTypeAttribute attribute or some alternative mechanism to allow the use of derived types. Betrachten Sie den folgenden Vorgang.Consider the following operation.

[OperationContract]  
public bool IsLibraryItemAvailable(LibraryItem item);  
<OperationContract()>  
    Function IsLibraryItemAvailable(item As LibraryItem) As Boolean  

Angenommen, zwei Typen, Book und Magazine, werden aus LibraryItem abgeleitet.Assume that two types, Book and Magazine, derive from LibraryItem. Um diese Typen im IsLibraryItemAvailable-Vorgang zu verwenden, können Sie den Vorgang wie folgt ändern:To use these types in the IsLibraryItemAvailable operation, you can change the operation as follows:

[OperationContract]

[ServiceKnownType(typeof(Book))]

[ServiceKnownType(typeof(Magazine))]

public bool IsLibraryItemAvailable(LibraryItem item);

Alternativ dazu können Sie, wie im folgenden Beispielcode dargestellt, das KnownTypeAttribute-Attribut verwenden, wenn das Standard-DataContractSerializer verwendet wird.Alternatively, you can use the KnownTypeAttribute attribute when the default DataContractSerializer is in use, as shown in the following example code.

[OperationContract]  
public bool IsLibraryItemAvailable(LibraryItem item);  

// code omitted   

[DataContract]  
[KnownType(typeof(Book))]  
[KnownType(typeof(Magazine))]  
public class LibraryItem  
{  
    //code omitted  
}  
<OperationContract()>  
Function IsLibraryItemAvailable(item As LibraryItem) As Boolean  

'Code Omitted  
<DataContract()>  
<KnownType(GetType(Book))>  
<KnownType(GetType(Magazine))>  
Public Class LibraryItem  
  'Code Omitted  
End Class  

Sie können das XmlIncludeAttribute-Attribut verwenden, wenn Sie XmlSerializer verwenden.You can use the XmlIncludeAttribute attribute when using the XmlSerializer.

Sie können das ServiceKnownTypeAttribute-Attribut auf einen Vorgang oder auf den gesamten Dienst anwenden.You can apply the ServiceKnownTypeAttribute attribute to an operation or to the entire service. Es akzeptiert entweder einen Typ oder den Namen der Methode, die aufgerufen werden soll, um eine Liste bekannter Typen zu erzeugen, genau wie das KnownTypeAttribute-Attribut.It accepts either a type or the name of the method to call to get a list of known types, just like the KnownTypeAttribute attribute. Weitere Informationen finden Sie unter Datenvertragstypen bezeichnet.For more information, see Data Contract Known Types.

Angeben der Verwendung und des StilsSpecifying the Use and Style

Bei der Beschreibung von Diensten mithilfe von Web Services Description Language (WSDL) sind die beiden am häufigsten verwendeten Stile der Dokumentstil und der Remoteprozeduraufruf (RPC, remote procedure call).When describing services using Web Services Description Language (WSDL), the two commonly used styles are Document and remote procedure call (RPC). Beim Dokumentstil wird der gesamte Nachrichtentext mithilfe des Schemas beschrieben, und WSDL beschreibt die verschiedenen Nachrichtentextteile durch Verweisen auf Elemente innerhalb dieses Schemas.In the Document style, the entire message body is described using the schema, and the WSDL describes the various message body parts by referring to elements within that schema. Beim RPC-Stil verweist WSDL auf einen Schematyp für jeden Nachrichtenteil statt auf ein Element.In the RPC style, the WSDL refers to a schema type for each message part rather than an element. In einigen Fällen müssen Sie einen dieser Stile manuell auswählen.In some cases, you have to manually select one of these styles. Zu diesem Zweck können Sie das DataContractFormatAttribute-Attribut anwenden und die Style-Eigenschaft festlegen (wenn das DataContractSerializer verwendet wird), oder Sie legen Style in dem XmlSerializerFormatAttribute-Attribut fest (wenn das XmlSerializer verwendet wird).You can do this by applying the DataContractFormatAttribute attribute and setting the Style property (when the DataContractSerializer is in use), or by setting Style on the XmlSerializerFormatAttribute attribute (when using the XmlSerializer).

Außerdem unterstützt der XmlSerializer zwei Formen von serialisiertem XML: Literal und Encoded.Additionally, the XmlSerializer supports two forms of serialized XML: Literal and Encoded. Literal ist die am häufigsten akzeptierte Form und die einzige Form, die vom DataContractSerializer unterstützt wird.Literal is the most commonly accepted form, and is the only form the DataContractSerializer supports. Encoded ist eine Legacyform, die in Abschnitt 5 der SOAP-Spezifikation beschrieben wird. Sie wird für neue Dienste nicht empfohlen.Encoded is a legacy form described in section 5 of the SOAP specification, and is not recommended for new services. Um zum Encoded-Modus zu wechseln, legen Sie die Use-Eigenschaft für das XmlSerializerFormatAttribute-Attribut auf Encoded fest.To switch to Encoded mode, set the Use property on the XmlSerializerFormatAttribute attribute to Encoded.

In den meisten Fällen sollten Sie die Standardeinstellungen für die Style- und die Use-Eigenschaft nicht ändern.In most cases, you should not change the default settings for the Style and Use properties.

Kontrollieren des SerialisierungsprozessesControlling the Serialization Process

Es gibt eine Reihe von Möglichkeiten, die Art und Weise anzupassen, in der Daten serialisiert werden.You can do a number of things to customize the way data is serialized.

Ändern der ServerserialisierungseinstellungenChanging Server Serialization Settings

Wenn das Standard-DataContractSerializer verwendet wird, können Sie einige Aspekte des Serialisierungsprozesses für den Dienst durch Anwenden des ServiceBehaviorAttribute-Attributs auf den Dienst steuern.When the default DataContractSerializer is in use, you can control some aspects of the serialization process on the service by applying the ServiceBehaviorAttribute attribute to the service. Sie können insbesondere die MaxItemsInObjectGraph-Eigenschaft verwenden, um das Kontingent festzulegen, das die maximale Anzahl an Objekten einschränkt, die das DataContractSerializer deserialisiert.Specifically, you may use the MaxItemsInObjectGraph property to set the quota that limits the maximum number of objects the DataContractSerializer deserializes. Sie können die IgnoreExtensionDataObject-Eigenschaft verwenden, um die Roundtrip-Versionsverwaltungsfunktion zu deaktivieren.You can use the IgnoreExtensionDataObject property to turn off the round-tripping versioning feature. Weitere Informationen zu Kontingenten finden Sie unter Sicherheitsüberlegungen zu Daten.For more information about quotas, see Security Considerations for Data. Weitere Informationen zu Round-Tripping, finden Sie unter aufwärtskompatible Datenverträge.For more information about round-tripping, see Forward-Compatible Data Contracts.

[ServiceBehavior(MaxItemsInObjectGraph=100000)]  
public class MyDataService:IDataService  
{  
    public DataPoint[] GetData()  
    {  
       // Implementation omitted  
    }  
}  
<ServiceBehavior(MaxItemsInObjectGraph:=100000)>  
Public Class MyDataService Implements IDataService  

    Function GetData() As DataPoint()  
         ‘ Implementation omitted  
    End Function  
End Interface  

SerialisierungsverhaltenSerialization Behaviors

Zwei Verhalten in WCF, stehen die DataContractSerializerOperationBehavior und die XmlSerializerOperationBehavior , die automatisch geladen werden, je nachdem, welches Serialisierungsprogramm für einen bestimmten Vorgang verwendet wird.Two behaviors are available in WCF, the DataContractSerializerOperationBehavior and the XmlSerializerOperationBehavior that are automatically plugged in depending on which serializer is in use for a particular operation. Da diese Arten von Verhalten automatisch angewendet werden, müssen Sie sie normalerweise nicht beachten.Because these behaviors are applied automatically, you normally do not have to be aware of them.

DataContractSerializerOperationBehavior weist jedoch die MaxItemsInObjectGraph-, die IgnoreExtensionDataObject- und die DataContractSurrogate-Eigenschaften auf, die Sie zur Anpassung des Serialisierungsprozesses verwenden können.However, the DataContractSerializerOperationBehavior has the MaxItemsInObjectGraph, IgnoreExtensionDataObject, and DataContractSurrogate properties that you may use to customize the serialization process. Die ersten beiden Eigenschaften haben die gleiche Bedeutung, wie im vorherigen Abschnitt erläutert.The first two properties have the same meaning as discussed in the previous section. Sie können die DataContractSurrogate-Eigenschaft verwenden, um Datenvertrag-Ersatzzeichen zu aktivieren, die ein leistungsfähiges Werkzeug zum Anpassen und Erweitern des Serialisierungsprozesses darstellen.You can use the DataContractSurrogate property to enable data contract surrogates, which are a powerful mechanism for customizing and extending the serialization process. Weitere Informationen finden Sie unter Datenvertrag-Ersatzzeichen.For more information, see Data Contract Surrogates.

Sie können das DataContractSerializerOperationBehavior verwenden, um sowohl die Client- als auch die Serverserialisierung anzupassen.You can use the DataContractSerializerOperationBehavior to customize both client and server serialization. Im folgenden Beispiel wird das Erhöhen des MaxItemsInObjectGraph-Kontingents für den Client veranschaulicht.The following example shows how to increase the MaxItemsInObjectGraph quota on the client.

ChannelFactory<IDataService> factory = new ChannelFactory<IDataService>(binding, address);  
foreach (OperationDescription op in factory.Endpoint.Contract.Operations)  
{  
    DataContractSerializerOperationBehavior dataContractBehavior =  
                op.Behaviors.Find<DataContractSerializerOperationBehavior>()  
                as DataContractSerializerOperationBehavior;  
    if (dataContractBehavior != null)  
    {  
        dataContractBehavior.MaxItemsInObjectGraph = 100000;  
    }  
}  
IDataService client = factory.CreateChannel();  
Dim factory As ChannelFactory(Of IDataService) = New ChannelFactory(Of IDataService)(binding, address)  
For Each op As OperationDescription In factory.Endpoint.Contract.Operations  
        Dim dataContractBehavior As DataContractSerializerOperationBehavior = op.Behaviors.Find(Of DataContractSerializerOperationBehavior)()  
        If dataContractBehavior IsNot Nothing Then  
            dataContractBehavior.MaxItemsInObjectGraph = 100000  
        End If  
     Next  
    Dim client As IDataService = factory.CreateChannel  

Es folgt der entsprechende Code für den Dienst, falls er selbst gehostet wird.Following is the equivalent code on the service, in the self-hosted case.

ServiceHost serviceHost = new ServiceHost(typeof(IDataService))  
foreach (ServiceEndpoint ep in serviceHost.Description.Endpoints)  
{  
foreach (OperationDescription op in ep.Contract.Operations)  
{  
        DataContractSerializerOperationBehavior dataContractBehavior =  
           op.Behaviors.Find<DataContractSerializerOperationBehavior>()  
                as DataContractSerializerOperationBehavior;  
        if (dataContractBehavior != null)  
        {  
            dataContractBehavior.MaxItemsInObjectGraph = 100000;  
        }  
}  
}  
serviceHost.Open();  
Dim serviceHost As ServiceHost = New ServiceHost(GetType(IDataService))  
        For Each ep As ServiceEndpoint In serviceHost.Description.Endpoints  
            For Each op As OperationDescription In ep.Contract.Operations  
                Dim dataContractBehavior As DataContractSerializerOperationBehavior = op.Behaviors.Find(Of DataContractSerializerOperationBehavior)()  

                If dataContractBehavior IsNot Nothing Then  
                    dataContractBehavior.MaxItemsInObjectGraph = 100000  
                End If  
            Next  
        Next  
        serviceHost.Open()  

Falls er im Internet gehostet wird, müssen Sie eine neue abgeleitete ServiceHost-Klasse erstellen und die Diensthostfactory verwenden, um sie zu laden.In the Web-hosted case, you must create a new ServiceHost derived class and use a service host factory to plug it in.

Steuern von Serialisierungseinstellungen in der KonfigurationControlling Serialization Settings in Configuration

MaxItemsInObjectGraph und IgnoreExtensionDataObject können über die Konfiguration mithilfe des dataContractSerializer-Endpunkts oder -Dienstverhaltens gesteuert werden, wie im folgenden Beispiel dargestellt wird.The MaxItemsInObjectGraph and IgnoreExtensionDataObject can be controlled through configuration by using the dataContractSerializer endpoint or service behavior, as shown in the following example.

<configuration>  
    <system.serviceModel>  
        <behaviors>  
            <endpointBehaviors>  
                <behavior name="LargeQuotaBehavior">  
                    <dataContractSerializer  
                      maxItemsInObjectGraph="100000" />  
                </behavior>  
            </endpointBehaviors>  
        </behaviors>  
        <client>  
            <endpoint address=http://example.com/myservice  
                  behaviorConfiguration="LargeQuotaBehavior"  
                binding="basicHttpBinding" bindingConfiguration=""   
                            contract="IDataService"  
                name="" />  
        </client>  
    </system.serviceModel>  
</configuration>  

Serialisierung von gemeinsamen Typen, Objektdiagrammbeibehaltung und benutzerdefinierte SerialisierungsprogrammeShared Type Serialization, Object Graph Preservation, and Custom Serializers

Das DataContractSerializer serialisiert mithilfe von Datenvertragsnamen und nicht mithilfe von .NET-Typnamen.The DataContractSerializer serializes using data contract names and not .NET type names. Dies entspricht dienstorientierten Architekturgrundsätzen und ermöglicht einen hohen Grad an Flexibilität – die .NET-Typen können sich ändern, ohne sich auf den Übertragungsvertrag auszuwirken.This is consistent with service-oriented architecture tenets and allows for a great degree of flexibility—the .NET types can change without affecting the wire contract. In seltenen Fällen kann es notwendig sein, tatsächliche .NET-Typnamen zu serialisieren und dabei eine enge Verknüpfung zwischen dem Client und dem Server vorzunehmen, ähnlich wie bei der .NET-Framework-Remotetechnologie.In rare cases, you may want to serialize actual .NET type names, thereby introducing a tight coupling between the client and the server, similar to the .NET Framework remoting technology. Dies wird nicht empfohlen, außer in seltenen Fällen, die normalerweise auftreten, wenn von .NET Framework Remoting nach WCF migrieren.This is not a recommended practice, except in rare cases that usually occur when migrating to WCF from .NET Framework remoting. In diesem Fall müssen Sie die NetDataContractSerializer-Klasse statt der DataContractSerializer-Klasse verwenden.In this case, you must use the NetDataContractSerializer class instead of the DataContractSerializer class.

Das DataContractSerializer serialisiert normalerweise Objektdiagramme als Objektstrukturen, The DataContractSerializer normally serializes object graphs as object trees. d. h. auf dasselbe Objekt wird mehr als einmal verwiesen, es wird mehr als einmal serialisiert.That is, if the same object is referred to more than once, it is serialized more than once. Betrachten Sie z. B. eine PurchaseOrder-Instanz, die über zwei Felder vom Typ Adresse mit den Namen billTo und shipTo verfügt.For example, consider a PurchaseOrder instance that has two fields of type Address called billTo and shipTo. Wenn beide Felder auf dieselbe Adressinstanz festgelegt werden, gibt es zwei identische Adressinstanzen nach der Serialisierung und der Deserialisierung.If both fields are set to the same Address instance, there are two identical Address instances after serialization and deserialization. Dies erfolgt, weil es kein interoperables Standardverfahren zur Darstellung von Objektdiagrammen in XML gibt (außer dem älteren SOAP-Codierungsstandard, der für XmlSerializer verfügbar ist, wie im vorigen Abschnitt über Style und Use beschrieben).This is done because there is no standard interoperable way to represent object graphs in XML (except for the legacy SOAP encoded standard available on the XmlSerializer, as described in the previous section on Style and Use). Objektdiagramme als Strukturen zu serialisieren, bringt gewisse Nachteile mit sich, z. B. können Diagramme mit Zirkelverweisen nicht serialisiert werden.Serializing object graphs as trees has certain disadvantages, for example, graphs with circular references cannot be serialized. Gelegentlich ist es erforderlich, auf echte Objektdiagrammserialisierung umzustellen, obwohl sie nicht interoperabel ist.Occasionally, it is necessary to switch to true object graph serialization, even though it is not interoperable. Dies kann durch Verwendung vom DataContractSerializer erfolgen, das mit dem preserveObjectReferences-Parameter konstruiert ist, der auf true festgelegt ist.This can be done by using the DataContractSerializer constructed with the preserveObjectReferences parameter set to true.

Gelegentlich reichen die integrierten Serialisierungsprogramme nicht für das Szenario aus.Occasionally, the built-in serializers are not enough for your scenario. In den meisten Fällen können Sie trotzdem die XmlObjectSerializer-Abstraktion verwenden, von der sowohl das DataContractSerializer als auch das NetDataContractSerializer abgeleitet werden.In most cases, you can still use the XmlObjectSerializer abstraction from which both the DataContractSerializer and the NetDataContractSerializer derive.

Die drei vorherigen Fälle (.NET-Typbeibehaltung, Objektdiagrammbeibehaltung und die vollkommen benutzerdefinierte XmlObjectSerializer-basierte Serialisierung) erfordern alle die Einbindung eines benutzerdefinierten Serialisierungsprogramms.The previous three cases (.NET type preservation, object graph preservation, and completely custom XmlObjectSerializer-based serialization) all require a custom serializer be plugged in. Gehen Sie hierzu folgendermaßen vor:To do this, perform the following steps:

  1. Schreiben Sie ein eigenes Verhalten, das sich vom DataContractSerializerOperationBehavior herleitet.Write your own behavior deriving from the DataContractSerializerOperationBehavior.

  2. Überschreiben Sie die beiden CreateSerializer-Methoden, um Ihr eigenes Serialisierungsprogramm zurückzugeben (entweder das NetDataContractSerializer, DataContractSerializer mit preserveObjectReferences festgelegt auf true oder Ihr eigenes benutzerdefiniertes XmlObjectSerializer).Override the two CreateSerializer methods to return your own serializer (either the NetDataContractSerializer, the DataContractSerializer with preserveObjectReferences set to true, or your own custom XmlObjectSerializer).

  3. Vor dem Öffnen des Diensthosts oder dem Erstellen eines Clientkanals entfernen Sie das vorhandene DataContractSerializerOperationBehavior-Verhalten und binden die benutzerdefinierte abgeleitete Klasse ein, die Sie in den vorherigen Schritten erstellt haben.Before opening the service host or creating a client channel, remove the existing DataContractSerializerOperationBehavior behavior and plug in the custom derived class that you created in the previous steps.

Weitere Informationen zu erweiterten Serialisierung Konzepten finden Sie unter Serialisierung und Deserialisierung.For more information about advanced serialization concepts, see Serialization and Deserialization.

Siehe auchSee Also

Verwenden der XmlSerializer-KlasseUsing the XmlSerializer Class
Vorgehensweise: Aktivieren von StreamingHow to: Enable Streaming
Vorgehensweise: Erstellen eines grundlegenden Datenvertrags für eine Klasse oder StrukturHow to: Create a Basic Data Contract for a Class or Structure