WCF provides a message-oriented programming model, with flexibility in its use.
All WCF messages are modelled with System.ServiceModel.Channels.Message.
They can be encoded as XML, JSON, binary etc. They can also optionally be mapped to/from .Net objects (see serializing, below).
The MessageVersion class allows the specifying of the versions of SOAP and WS-Addressing that you wish to use (if any).
As the message class has been designed to support streaming, the body of a message can only be processed once for a particular instance. You can copy the body if you need to process the message more than once. The message has a state property which will be either Created, Read, Written, Copied or Closed.
The message has a Headers property which can hold values about the message. It is typically the job of intermediaries to process the message headers. Intermediaries often need to store the results of their processing somewhere for future use in the processing pipeline, which is why a message also have a message properties collection. The properties are usually only used during local processing, and don't usually affect what happens to the message on the wire, but they are able to.
Message bodies can be read from by calling either GetBody
Action values of the OperationContract can be used to map messages to methods, and these can be either universal one-way or two-way operations. Operations can either be "*" or named specifically.
Data and Message Contracts
The data contract defines the format of the message body that will be passed in the message. It is done by annotating classes with the [DataContract] and [DataMember] attributes. An example is shown below:
public class Person
public string PersonID; //This property will not be in the message
public string Name;
public int Age;
A data contract will break if any of the following changes are made:
Changing the type Name or Namespace
Changing the Order of data members
Changing the Name of a data member
Changing the type of a data member
Changing IsRequired property from false to true
Message contracts map data contracts to SOAP envelopes. They allow full control to model SOAP messages and headers, by annotating the class with [MessageContract], [MessageBodyMember] and [MessageHeader] attributes on members.
Messages can be serialised into .Net objects using one of the supported serializers. This allows objects to be sent easily using WCF. Messages can be "typed" to .Net types by annotating the types with special mapping attributes. At runtime a serializer maps the .Net objects into messages.
The XmlSerializer is the original serializer from .Net 1.0, and is still fully supported, and offers backwards compatibility to web (ASMX) services and other Non-WCF services.
The DataContractSerializer is a new serialiser in .Net 3.0 that supports most .Net types including:
CLR built in types,
Byte Array, DateTime, TimeSpan, GUID, XmlQualifiedName, XmlElement, XmlNode arrays
Types marked with the DataContract or CollectionDataContract attribute
Types that implment IXmlSerializable
Arrays/Collection classes including List
, Dictionary and HastTable
Types marked with Serializable attribute or implement Iserializable
Note that the DCS only supports a subset of XSD
In .Net 3.5 the DataContractJSONSerializer was added, that perfoms the same as the DCS but with serializing to JSON instead of XML.
Message-oriented Design Techniques
Pure XML messaging approaches are gaining more traction these days. This is very like REST.
Schema-first design is common in integration scenarios, specially where collaboration and parallel development is required. Data/message contracts can be generated from schemas using SvcUtil.exe. XmlSerializer (and xsd.exe) is the recommended approach here.
Code-first design is more common when collaboration isn't needed, where the developer writes data contracts and lets WCF generate the schemas. DataContractSerializer (and SvcUtil.exe) is the recommended approach here.