Using MessageContract to control the SOAP message
DataContract
can help us design the data types used in a WCF service. However, this only covers the data members (variables and parameters used in operation) serialized in the underlying SOAP message. Sometimes we also need to control the structure and format of the entire SOAP message.
WCF introduces a MessageContract
concept, which helps service developers to model the structure and format of the entire message of a given service operation. Actually, we can take MessageContract
type as a special DataContract
type, which is marked by the MessageContractAttribute
. This recipe will show you how we can define a typical MessageContract
for our WCF service operation to control the format of the underlying SOAP XML message.
How to do it...
Define a custom data type that represents the entire SOAP message body content. Use
MessageContractAttribute
to decorate the type andMessageBodyMemberAttribute
to mark class members that will be embedded in the SOAP message body. The following code demonstrates a sampleMessageContract
pair—one is for operation request and the other for operation response.[MessageContract(WrapperName="Hello",WrapperNamespace="http:// wcftest.org/messagecontract")] public class HelloRequest { [MessageBodyMember(Name="Who")] public string User { get; set; } } [MessageContract(WrapperName="HelloResponse",WrapperNamespace="http://wcftest.org/messagecontract")] public class HelloResponse { [MessageBodyMember(Name="Reply")] public string ReplyContent { get; set; } }
After defining the
MessageContract
types for request/response operation, we need to use them as the input parameter (the only input parameter) and return value of the operation's implementation (see the followingSayHello
operation):[OperationContract] HelloResponse SayHello(HelloRequest req);
In the
SayHello
operation,HelloRequest
is the only input parameter andHelloResponse
represents the return value.
How it works...
Types marked with MessageContractAttribute
can be used to represent the entire SOAP envelope body. The serialization of such types still follows the rules for normal DataContract
types.
Also, it is important that operations which use MessageContract
to control the SOAP envelope only have a single input parameter and return value. This is because only that input parameter will be serialized as the entire SOAP request body, and the return value will be serialized as the entire SOAP response body.
By capturing the SOAP request/response on wire, we can find that the serialized SOAP message content conforms to the MessageContract
definition (refer to the next two screenshots):
See also
Creating a service via ChannelListener in Chapter 5
Complete source code for this recipe can be found in the
\Chapter 1\recipe5\
folder