In a calling application, the service model layer is responsible for translating method invocations in application code into outbound messages, pushing them to the underlying channels, translating results back into return values and out parameters in application code, and returning the results back to the caller. Service model extensions modify or implement execution or communication behavior and features involving client or dispatcher functionality, custom behaviors, message and parameter interception, and other extensibility functionality.
This topic describes how to use the ClientRuntime and ClientOperation classes in a Windows Communication Foundation (WCF) client application to modify the default execution behavior of a WCF client or to intercept or modify messages, parameters, or return values prior to or subsequent to sending or retrieving them from the channel layer. For more information about extending the service runtime, see Extending Dispatchers. For more information about the behaviors that modify and insert customization objects into the client runtime, see Configuring and Extending the Runtime with Behaviors.
On a client, a WCF client object or client channel converts method invocations into outgoing messages and incoming messages to operation results that are returned to the calling application. (For more information about client types, see WCF Client Architecture.)
WCF client types have runtime types that handle this endpoint- and operation-level functionality. When an application calls an operation, the ClientOperation translates the outbound objects into a message, processes interceptors, confirms that the outbound call conforms to the target contract, and hands the outbound message to the ClientRuntime, which is responsible for creating and managing outbound channels (and inbound channels in the case of duplex services), handling extra outbound message processing (such as header modification), processing message interceptors in both directions, and routing inbound duplex calls to the appropriate client-side DispatchRuntime object. Both the ClientOperation and ClientRuntime provide similar services when messages (including faults) are returned to the client.
These two runtime classes are the main extension to customize the processing of WCF client objects and channels. The ClientRuntime class allows users to intercept and extend client execution across all messages in the contract. The ClientOperation class allows users to intercept and extend client execution for all messages in a given operation.
Modifying the properties or inserting customizations are done by using contract, endpoint, and operation behaviors. For more information about how to use these types of behaviors to perform client runtime customizations, see Configuring and Extending the Runtime with Behaviors.
There a number of reasons to extend the client system, including:
Custom Message Validation. A user may want to enforce that a message is valid for a certain schema. This can be done by implementing the IClientMessageInspector interface and assigning the implementation to the MessageInspectors property. For examples, see How to: Inspect or Modify Messages on the Client and How to: Inspect or Modify Messages on the Client.
Custom Message Logging. A user may want to inspect and log some set of application messages that flow through an endpoint. This can also be accomplished with the message interceptor interfaces.
Custom Message Transformations. Rather than modifying application code, the user may want to apply certain transformations to the message in the runtime (for example, for versioning). This can be accomplished, again, with the message interceptor interfaces.
Custom Data Model. A user may want to have a data or serialization model other than those supported by default in WCF (namely, System.Runtime.Serialization.DataContractSerializer, System.Xml.Serialization.XmlSerializer, and System.ServiceModel.Channels.Message objects). This can be done by implementing the message formatter interfaces. For more information, see System.ServiceModel.Dispatcher.IClientMessageFormatter and the ClientOperation.Formatter property.
Custom Parameter Validation. A user may want to enforce that typed parameters are valid (as opposed to XML). This can be done using the parameter inspector interfaces. For an example, see How to: Inspect or Modify Parameters or Client Validation.
Using the ClientRuntime Class
The ClientRuntime class is an extensibility point to which you can add extension objects that intercept messages and extend client behavior. Interception objects can process all messages in a particular contract, process only messages for particular operations, perform custom channel initialization, and implement other custom client application behavior.
The CallbackDispatchRuntime property returns the dispatch run-time object for service-initiated callback clients.
The OperationSelector property accepts a custom operation selector object.
The ChannelInitializers property enables the addition of a channel initializer that can inspect or modify the client channel.
The ManualAddressing property enables an application to turn off some automatic addressing headers to directly control addressing.
The Via property sets the value of the destination of the message at the transport level to support intermediaries and other scenarios.
In addition, there are a number of other properties that retrieve the contract information:
If the WCF client is a duplex WCF client, the following properties also retrieve the callback WCF client information:
To extend WCF client execution across an entire WCF client, review the properties available on the ClientRuntime class to see whether modifying a property or implementing an interface and adding it to a property creates the functionality you are seeking. Once you have chosen a particular extension to build, insert your extension into the appropriate ClientRuntime property by implementing a client behavior that provides access to the ClientRuntime class when invoked.
You can insert custom extension objects into a collection using an operation behavior (an object that implements IOperationBehavior), a contract behavior (an object that implements IContractBehavior), or an endpoint behavior (an object that implements IEndpointBehavior). The installing behavior object is added to the appropriate collection of behaviors either programmatically, declaratively (by implementing a custom attribute), or by implementing a custom BehaviorExtensionElement object to enable the behavior to be inserted using an application configuration file. For details, see Configuring and Extending the Runtime with Behaviors.
For examples that demonstrate interception across a WCF client, see How to: Inspect or Modify Messages on the Client.
Using the ClientOperation Class
The ClientOperation class is the location for client run-time modifications and insertion point for custom extensions that are scoped to only one service operation. (To modify client run-time behavior for all messages in a contract, use the ClientRuntime class.)
Use the Operations property to locate the ClientOperation object that represents a particular service operation. The following properties enable you to insert custom objects into the WCF client system:
The following properties enable you to modify the system in interaction with the formatter and custom parameter inspectors:
Use the SerializeRequest property to control the serialization of an outbound message.
Use the DeserializeReply property to control the deserialization of an inbound message.
Use the Action property to control the WS-Addressing action of the request message.
Use the FaultContractInfos property to get a collection that contains the types that can appear in SOAP faults as the detail type.
Use the IsOneWay property to control whether the operation is a one-way operation.
Use the Name property to get the name of the operation.
Use the SyncMethod property to control which method is mapped to the operation.
To extend WCF client execution across only one service operation, review the properties available on the ClientOperation class to see whether modifying a property or implementing an interface and adding it to a property creates the functionality you are seeking. Once you have chosen a particular extension to build, insert your extension into the appropriate ClientOperation property by implementing a client behavior that provides access to the ClientOperation class when invoked. Inside that behavior you can then modify the ClientRuntime property to fit your requirements.
Typically, implementing an operation behavior (an object that implements the IOperationBehavior interface) suffices, but you can also use endpoint behaviors and contract behaviors to accomplish the same thing by locating the OperationDescription for a particular operation and attaching the behavior there. For details, see Configuring and Extending the Runtime with Behaviors.
To use your custom behavior from configuration, install your behavior using a custom behavior configuration section handler. You can also install your behavior by creating a custom attribute.
For examples that demonstrate interception across a WCF client, see How to: Inspect or Modify Parameters.