A contract defines what functionality a service offers and what functionality can be used by the client. The contract can be completely independent of the implementation of the service.
The contracts defined by WCF can be grouped into three different contract types: data, service, and message. The contracts can be specified by using .NET attributes:
Data contract – The data contract defines the data received by and returned from the service. The classes used for sending and receiving messages have data contract attributes associated.
Service contract – The service contract is used to define the WSDL that describes the service. This contract is defined with interfaces or classes.
Message contract – If complete control over the SOAP message is needed, a message contract can specify what data should go into the SOAP header, and what belongs in the SOAP body.
The following sections explore these contract types further.
With the data contract, CLR types are mapped to XML schemas. The data contract is different from other .NET serialization mechanisms: with runtime serialization, all fields are serialized (including private fields) with XML serialization only the public fields and properties are serialized. The data contract requires explicit marking of the fields that should be serialized with the (Data Member) attribute. This attribute can be used regardless of whether the field is private or public, or if it is applied to a property.
To be platform-independent, and give the option to change data with new versions without breaking older clients and services, using data contracts is the best way to define which data should be sent. However, you can also use XML serialization and runtime serialization. XML serialization is the mechanism used by ASP.NET Web services; .NET Remoting uses runtime serialization.
With the attribute (Data Member), you can specify the properties described in the following table.
When you create a new version of a data contract, pay attention to the kind of change and act accordingly if old and new clients and old and new services should be supported simultaneously.
When defining a contract, you should add XML namespace information with the Namespace property of the DataContractAttribute. This namespace should be changed if a new version of the data contract is created that breaks compatibility. If just optional members are added, the contract is [lot broken – this is a compatible change. Old clients can still send a message to the new service because the additional data is not needed. New clients can send messages to an old service because the old service just ignores the additional data.
Removing fields or adding required fields breaks the contract. Here, you should also change the XML namespace. The name of the namespace can include the year and the month,Every time a breaking change is done, the namespace is changed; for example, by changing the year and month to the actual value.
The service contract defines the operations the service can perform. The attribute [ServiceContract] is used with interfaces or classes to define a service contract. The methods that are offered by the service have the attribute [OperationContract] applied, as you can see with the interface IRoomService:
The possible properties that you can set with the [ServiceContract] attribute are described in the following table.
With the [OperationContract], you can specify properties as shown in the following table.
With the service contract, you can also define the requirements that the service has from the transport with the attribute (DeliveryRequirements). The property Require Ordered Delivery defines that the messages sent must arrive in the same order. With the property Queued Delivery Requirements, you can define that the message is sent in a disconnected mode, for example, by using Message Queuing (covered in Chapter 45).
A message contract is used if complete control over the SOAP message is needed. With the message contract, you can specify what part of the message should go into the SOAP header and what belongs in the SOAP body. The following example shows a message contract for the class Process Person Request Message. The message contract is specified with the attribute (MessageContract). The header and body of the SOAP message are specified with the attributes (MessageHeader) and (MessageBodyMember). By specifying the Position property, you can define the element order within the body. You can also specify the protection level for header and body fields.
The class Process Person Request Message is used with the service contract that is defined with the interface IProcessPerson: