- Background
- XmlSerializer and XmlFormatter
- The XML Fetish
- Using the XmlFormatter
- Exception Handling
- Summary
- References
XmlSerializer and XmlFormatter
From the foregoing, it should be apparent that data being sent from the client to the service is serialized to XML within the client, and deserialized from XML within the service. There are two XML serializers that the Windows Communication Foundation can use to accomplish that task.
One of those is a new XML serializer provided with the Windows Communication Foundation. It is the XmlFormatter class in the System.Runtime.Serialization namespace within the System.Runtime.Serialization assembly. That assembly is one of the constituent assemblies of the Windows Communication Foundation. The XmlFormatter class is the XML serializer that the Windows Communication Foundation uses by default.
Given a class like the one in Listing 3.1, one could make the class serializable by the XmlFormatter by adding DataContract and DataMember attributes as shown in Listing 3.2. The representation of instances of a class in XML that is implied by the addition of the DataContract attribute to the class, and the DataMember attributes to its members, is commonly referred to as a data contract in the argot of the Windows Communication Foundation.
Example 3.1. DerivativesCalculation Class
public class DerivativesCalculation { private string[] symbols; private decimal[] parameters; private string[] functions; public string[] Symbols { get { return this.symbols; } set { this.symbols = value; } } public decimal[] Parameters { get { return this.parameters; } set { this.parameters = value; } } public string[] Functions { get { return this.functions; } set { this.functions = value; } } }
Example 3.2. DerivativesCalculation Data Contract
[DataContract] public class DerivativesCalculation { [DataMember] private string[] symbols; [DataMember] private decimal[] parameters; [DataMember] private string[] functions; public string[] Symbols { get { return this.symbols; } set { this.symbols = value; } } public decimal[] Parameters { get { return this.parameters; } set { this.parameters = value; } } public string[] Functions { get { return this.functions; } set { this.functions = value; } } }
Although the XmlFormatter is the default XML serializer of the Windows Communication Foundation, the Windows Communication Foundation can also be configured to do XML serialization using the System.Xml.Serialization.XmlSerializer class that has always been included in the System.Xml assembly of the .NET Framework Class Library. To exercise that option, add the XmlSerializerFormat attribute to the definition of a Windows Communication Foundation contract, like so:
namespace DerivativesCalculator { [ServiceContract] [XmlSerializerFormat] public interface IDerivativesCalculator { [OperationContract] decimal CalculateDerivative( string[] symbols, decimal[] parameters, string[] functions); void DoNothing(); } }
The option of using the XmlSerializer class for XML serialization can also be selected just for individual operations:
namespace DerivativesCalculator { [ServiceContract] public interface IDerivativesCalculator { [OperationContract] [XmlSerializerFormat] decimal CalculateDerivative( string[] symbols, decimal[] parameters, string[] functions); void DoNothing(); } }
The XmlSerializer provides very precise control over how data is to be represented in XML. Its facilities are well documented in the book .NET Web Services: Architecture and Implementation, by Keith Ballinger (2003).
The XmlFormatter, on the other hand, provides very little control over how data is to be represented in XML. It only allows one to specify the namespaces and names used to refer to data items in the XML, and the order in which the data items are to appear in the XML, as in this case:
[DataContract(Namespace="Derivatives",Name="Calculation")] public class DerivativesCalculation { [DataMember(Namespace="Derivatives",Name="Symbols",Order=0)] private string[] symbols; [DataMember(Namespace="Derivatives",Name="Parameters",Order=1)] private decimal[] parameters;} [...] }
By not permitting any control over how data is to be represented in XML, the serialization process becomes highly predictable for the XmlFormatter and, thereby, more amenable to optimization. So a practical benefit of the XmlFormatter's design is better performance, approximately 10% better performance.