Services implement the logic for the operations defined by their service contract. Service endpoints describe which contract is in effect, what protocols should be employed, and the address used to reach the service. Any additional logic or configuration defining how the service should process messages that are applied locally to the service is encapsulated in a service behavior. Common examples of service behaviors you may have seen include the serviceMetadata behavior which is used to expose a WSDL for your services in support of proxy creation (such as that used by Visual Studio’s Add Service Reference), or serviceDebug which allows you to enable the inclusion of exception details in faults. Another common scenario for applying a custom service behavior is when your service is being hosted within AppFabric, and you need to apply additional configuration to it in the small window of time between when WAS initializes the service instance and when the service host is opened.
On the client side, the story is similar. One can use endpoint behaviors to alter the way the client proxy processes messages. An endpoint behavior is an easy way to plug in a Client Message Inspector to provide additional processing around when a message is sent or received by the client-side proxy.
In the article, we'll walk through the creation of both a custom service behavior and endpoint behavior, how to apply them via their respective configuration via *.config files, and what additional steps you must take when using them with AppFabric.
Creating a Custom Service Behavior
To illustrate the steps you need to follow to create a custom service behavior, we will pretend we are faced with a situation where we need to add an extension to the ServiceHost after it is initialized but before it opens. For example, in the documentation on using Promotable Properties of WCF Workflow Services, there is a sample that shows how you create an instance of a SqlWorkflowInstanceStoreBehavior, configure it, and call a method on it all before the host is opened. If you are self hosting the code is easy, as Figure 1 shows.
The challenge appears when you need to perform steps 3-6 with the ServiceHost instead created by IIS (as is the case when you are hosting services within AppFabric). How do you go about achieving this? Define a custom service behavior that is plugged in to your service through the web.config. The service behavior itself can apply whatever endpoint changes or add any extensions it needs to because it can access both the Service Description and ServiceHost instance, in a fashion similar to the code sample of Figure 1.
1. Enable configuration via web.config. Let’s start at the top by showing you how to handle a custom service behavior that has been added via the web.config. To do this, you must create a class derived from BehaviorExtensionElement which will be responsible for reading the element in config and returning an instance of your behavior by overriding the CreateBehavior method. The BehaviorExtensionElement class also supports retrieving additional properties (defined as attributes or nested elements on your behavior in the config) via overriding the Properties property, as Figure 2 shows.
2. Define the service behavior. With the ability to define the service behavior declaratively in place, let’s turn our attention to what it takes to create a custom service behavior. This is accomplished by implementing the System.ServiceModel.Description.IServiceBehavior interface and implementing the methods of interest to you during the application of your service behavior. There are only three methods to implement, and if your behavior will not be providing any additional logic you can leave their implementations empty.
- AddBindingParameters is used to pass additional configuration to the bindings used by the service.
- ApplyDispatchBehavior allows you to insert custom extensions or change runtime property values of the ServiceHost.
- Validate allows you to check for proper configuration before the ServiceHost is opened.
In our scenario, we are interested in taking steps 3-6 of Figure 1 to configure our service host as IIS is creating and initializing the ServiceHost, so we only need to fill in ApplyDispatchBehavior (see Figure 3).
The interesting point to observe from Figure 3 is that we are provided an instance of the ServiceHost, so we can access other behaviors already registered—in this case we access the SqlWorkflowInstanceStoreBehavior that was registered in the web.config (before ours).
3. Deploy and use the behavior. With the ServiceBehavior defined and the ServiceBehaviorElement that will load it from config constructed, we are ready to apply the custom service behavior to our service. Generally, you will package both your ServiceBehavior and the ServiceBehaviorElement in a single assembly. That assembly must be copied to the bin directory of your website, or if it’s signed added to the GAC.
To use the service behavior, you need to open up the web.config of your service and make two modifications. First, you need to instruct the configuration runtime how to process the XML of your behavior in config by telling it which Element class to use, as Figure 4 shows. This is done by adding an extensions element within the system.serviceModel element. To do that, you need to add a BehaviorExtensionElement that will contain an add element for each custom service behavior you plan on registering. The name of the add element must match the string value of the element name used within the behaviors element, and the type must refer to the BehaviorElement derived class (see Figure 4). Finally, to apply this service behavior to your service, you need to add it within the system.ServiceModel/serviceBehaviors/behaviors element that is used by your service. In Figure 4, notice how the element added there is “promoteProperties” which lines up with the value of the name attribute on the add element within the behaviorExtensions.
4. Update IIS configuration schema. Technically, that’s all there is to creating and registering a custom service behavior. However, if you try to look at the AppFabric Dashboard for a service configured this way you will get an error stating, in our case, that element “promoteProperties” is unrecognized. AppFabric and many IIS tools use the Microsoft.Web.Administration APIs to read the configuration. These APIs must be informed of the new schema element in the web.config as well. Doing so is easy: just create a new XML file and drop it in %SystemRoot%\system32\inetsrv\config\schema. This XML file needs to provide the schema for the behavior element in config. Figure 5 shows the complete contents of the XML file that would need to be added to support the promoteProperties element.
Creating a Custom Endpoint Behavior
Let’s turn our attention to the client side. Let’s say we wanted to add a Client Message Inspector to peek at either the messages before they are sent or the replies. Here we will use a custom endpoint behavior to plug in a Client Message Inspector.
1. Define a Client Message Inspector. For the purposes of this article, we want to use the Client Message Inspector generalized in Figure 6. Typically, a Client Message Inspector only has to provide implementation for the methods of interest within System.ServiceModel.Dispatcher.IClientMessageInspector. For example, we could add code within AfterReceiveReply to examine the reply message and perform additional processing on it or throw an exception if it didn’t meet our requirements.
2. Enable configuration via App.Config. With our message inspector defined, we turn our attention to how we register it with the proxy. In exactly the same was as for the service behavior, we will create BehaviorExtensionElement that returns an instance of the custom endpoint behavior. That endpoint behavior will, in turn, register the Client Message Inspector.
3. Defining the endpoint behavior. An endpoint behavior is created by providing implementation for System.ServiceModel.Description.IEndpointBehavior. As is typical for these implementations, we can leave empty implementation bodies for the methods that are of no interest to us. In our case, we want to modify the endpoint extensions of the client, so we override the ApplyClientBehavior and add our custom message inspector there, as Figure 7 shows.
4. Deploy and use the endpoint behavior. To utilize the custom endpoint behavior, you would compile the inspector, and then service behavior and element classes into an assembly that gets distributed with the client application. Within the app.config (or web.config) of the client, you need to perform nearly the same steps as you did for registering the service behavior: add an extension that references the element class and add the endpoint behavior to the collection of endpoint behaviors. Figure 8 shows how this is done for our sample. Notice that simpleBehavior is added beneath endpointBehaviors (as opposed to serviceBehaviors for the service behavior), but the extension is declared in exactly the same was as for a service behavior.
Extend WCF Services
By considering the two scenarios presented—how to register and create a custom service behavior and how to register and create a custom endpoint behavior—you should be well on your way to understanding how you leverage WCF’s extensibility when hosting within AppFabric.