Windows Communication Foundation (WCF) can use two different serialization technologies to turn the data in your application into XML that is transmitted between clients and services, a process called serialization. (DataContract and XML Serializer)
By default WCF uses the DataContractSerializer class to serialize data types. This serializer supports the following types:
Many .NET Framework types fall into the latter two categories and are thus serializable. Arrays of serializable types are also serializable. For a complete list, see Specifying Data Transfer in Service Contracts.
The DataContractSerializer, used together with data contract types, is the recommended way to write new WCF services. For more information, see Using Data Contracts.
WCF also supports the XmlSerializer class. The XmlSerializer class is not unique to WCF. It is the same serialization engine that ASP.NET Web services use. The XmlSerializer class supports a much narrower set of types than theDataContractSerializer class, but allows much more control over the resulting XML and supports much more of the XML Schema definition language (XSD) standard. It also does not require any declarative attributes on the serializable types. For more information, see the XML Serialization topic in the .NET Framework documentation. The XmlSerializer class does not support data contract types.
When using Svcutil.exe or the Add Service Reference feature in Visual Studio to generate client code for a third-party service, or to access a third-party schema, an appropriate serializer is automatically selected for you. If the schema is not compatible with the DataContractSerializer, the XmlSerializer is selected.
At times, you may have to manually switch to the XmlSerializer. This happens, for example, in the following cases:
In these and other cases, you can manually switch to the XmlSerializer class by applying the XmlSerializerFormatAttributeattribute to your service, as shown in the following code.
[ServiceContract] [XmlSerializerFormat] public class BankingService { [OperationContract] public void ProcessTransaction(BankingTransaction bt) { // Code not shown. } } //BankingTransaction is not a data contract class, //but is an XmlSerializer-compatible class instead. public class BankingTransaction { [XmlAttribute] public string Operation; [XmlElement] public Account fromAccount; [XmlElement] public Account toAccount; [XmlElement] public int amount; } //Notice that the Account class must also be XmlSerializer-compatible.
the DataContractSerializer class only serializes members marked with the DataMemberAttribute attribute when serializing data contract types. The XmlSerializer class serializes any public member. See the type in the following code.
[DataContract] public class Customer { [DataMember] public string firstName; [DataMember] public string lastName; public string creditCardNumber; }
If the type is inadvertently used in a service contract where the XmlSerializer class is selected, the creditCardNumber
member is serialized, which is probably not intended.
Even though the DataContractSerializer class is the default, you can explicitly select it for your service (although doing this should never be required) by applying the DataContractFormatAttribute attribute to the service contract type.
The serializer used for the service is an integral part of the contract and cannot be changed by selecting a different binding or by changing other configuration settings.
Other important security considerations apply to the XmlSerializer class. First, it is strongly recommended that any WCF application that uses the XmlSerializer class is signed with a key that is safeguarded from disclosure. This recommendation applies both when a manual switch to the XmlSerializer is performed and when an automatic switch is performed (by Svcutil.exe, Add Service Reference, or a similar tool). This is because the XmlSerializer serialization engine supports the loading of pre-generated serialization assemblies as long as they are signed with the same key as the application. An unsigned application is completely unprotected from the possibility of a malicious assembly matching the expected name of the pre-generated serialization assembly being placed in the application folder or the global assembly cache. Of course, an attacker must first gain write access to one of these two locations to attempt this action.
Another threat that exists whenever you use XmlSerializer is related to write access to the system temporary folder. TheXmlSerializer serialization engine creates and uses temporary serialization assemblies in this folder. You should be aware that any process with write access to the temporary folder may overwrite these serialization assemblies with malicious code.
You cannot directly apply XmlSerializer-compatible attributes to contract operation parameters or return values. However, they can be applied to typed messages (message contract body parts), as shown in the following code.
When applied to typed message members, these attributes override properties that conflict on the typed message attributes. For example, in the following code, ElementName
overrides Name
.
[ServiceContract] [XmlSerializerFormat] public class BankingService { [OperationContract] public void ProcessTransaction(BankingTransaction bt) { //Code not shown. } } [MessageContract] public class BankingTransaction { [MessageHeader] public string Operation; //This element will be <fromAcct> and not <from>: [XmlElement(ElementName="fromAcct"), MessageBodyMember(Name="from")] public Account fromAccount; [XmlElement, MessageBodyMember] public Account toAccount; [XmlAttribute, MessageBodyMember] public int amount; }
The MessageHeaderArrayAttribute attribute is not supported when using the XmlSerializer.
Note: |
---|
In this case, the XmlSerializer throws the following exception, which is released prior to WCF: "An element declared at the top level of a schema cannot have maxOccurs > 1. Provide a wrapper element for 'more' by using XmlArray orXmlArrayItem instead of XmlElementAttribute, or by using the Wrapped parameter style." If you receive such an exception, investigate whether this situation applies.
|
WCF does not support the SoapIncludeAttribute and XmlIncludeAttribute attributes in message contracts and operation contracts; use the KnownTypeAttribute attribute instead.