Friday 27 March 2009

Behind the Scenes of WCF

This entry is actually the one of a write up of my notes from previous DevWeeks. Although from 2008, this is still relevant today...

These notes follow on from Aaron Skonnard talk on this subject at DevWeek 2008.

Message Oriented WCF

WCF provides a message-oriented programming model, with flexibility in its use.

 

WCF Messages

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 or GetReadyAtBodyContents. The body can be written to by calling WriteMessage or WriteBody, passing in either an XmlDictionaryWriter or XmlWriter object.

 

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:

 

[DataContract]

public class Person

{

public string PersonID; //This property will not be in the message

[DataMember]

public string Name;

[DataMember]

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.

 

Serializing

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

  • Enums

  • 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.

No comments:

Post a Comment