This post is part of a series about WCF extensibility points. For a list of all previous posts and planned future ones, go to the index page.
The first part of this series will focus on the behaviors. There are four kinds of behaviors, depending on the scope to which they apply: service, endpoint, contract and operation behaviors. The behavior interfaces are the main entry points for almost all the other extensibility points in WCF – it’s via the Apply[Client/Dispatch]Behavior method in the behavior interfaces where a user can get a reference to most of them.
The WCF behaviors are part of a service (or endpoint / contract / operation) description – as opposed to the service runtime. The description of a service are all the objects that, well, describe what the service will be when it starts running – which happens when the host for the service is opened (e.g., in a self-hosted service, when the program calls ServiceHost.Open). When the service host instance is created, and endpoints are being added, no listeners (TCP sockets, HTTP listeners) have been started, and the program can modify the service description to define how it will behave once it’s running. That’s because, during the service setup, there are cases where the service is in an invalid state (for example, right after the ServiceHost instance is created, no endpoints are defined), so it doesn’t make sense for the host to be started at that point.
When Open is called on the host (or, in the case of an IIS/WAS-hosted service, when the first message arrives to activate the service), it initializes all the appropriate listeners, dispatchers, filters, channels, hooks, etc. that will cause an incoming message to be directed to the appropriate operation. Most of the extensibility points in WCF are actually part of the service runtime, and since the runtime is not initialized until the host is opened, the user needs a callback to notify it that the runtime is ready, and the hooks can be used.
The WCF behaviors are defined by four interfaces (on the System.ServiceModel.Description namespace): IServiceBehavior, IEndpointBehavior, IContractBehavior and IOperationBehavior. They all share the same pattern:
public interface I[Service/Endpoint/Contract/Operation]Behavior { void Validate(DescriptionObject); void AddBindingParameters(DescriptionObject, BindingParameterCollection); void ApplyDispatchBehavior(DescriptionObject, RuntimeObject); void ApplyClientBehavior(DescriptionObject, RuntimeObject); // not on IServiceBehavior }
The order in which the methods of the interfaces are called is the following:
Among each method, first the service behavior is called, then the contract, then the endpoint, and finally the operation behaviors within that contract.
The behaviors can be added in three different ways:
I don’t think there’s any “preferred” way of adding behaviors, it depends on the scenario. For example, if one wants to let an admin configure the behaviors without recompiling, configuration extensions are a good option; choosing between attribute and code is a choice between declarative and imperative implementation (I won’t go into that quasi-religious discussion here :)
Posts for each of the specific behavior interfaces, in which I’ll try to find real questions posted in the forum to show how those behaviors can be used to solve a realistic scenario.
[Code in this post]
[Back to the index]
Carlos Figueira http://blogs.msdn.com/carlosfigueira Twitter: @carlos_figueira http://twitter.com/carlos_figueira