Making WCF "Behave" - Part Three

When last we left our weary adventures, they had created a custom WCF Behavior based on the IDispatchMessageInspector that when attached to an endpoint of a WCF service intercepted the outgoing message and replaced it with it's own nefarious text (see here).

Their plan was brilliant! Brilliant that is, except for one minor detail.

You see, in their haste our motley crew had simply attached the behavior to the endpoint at runtime when the service host was initiated. They quickly realized that the real power of WCF is the ability to change behaviors via configuration. This would require a little more work...

Now, back to our story...

In order to be able to add our custom behavior through configuration, we need to make sure the WCF Service Model knows it exists. We do this by having our behavior inherit from System.ServiceModel.Configuration.BeahviorExtensionElement. This gives us an abstract property called "BehaviorType" which tells the service model the type of our custom Behavior, and an abstract method "CreateBehavior" which actually returns an instance of our custom behavior.

For this example I've chosen to implement this in my actual custom behavior class. And yes, if that was the way you do it all the time the service model should be smart enough to get the type and call a default constructor on our custom behavior. But the reason for this base class, and the methods it exposes, is that you could implement all of this in a class other than your actual behavior. This allows a lot of power in the way that custom behaviors are created, and I will cover strategies for this in another post.

Anyway...

If we add this to the custom behavior from last time, we get:

class MyCustomMessageFormatter : BehaviorExtensionElement,
    IDispatchMessageInspector, 
    IEndpointBehavior
{
    ...
    public override Type BehaviorType
    {
        get 
        { 
            return typeof(MyCustomMessageFormatter);
        }
    }

    protected override object CreateBehavior()
    {
        return new MyCustomMessageFormatter();
    }
}    

The next step is to let your application know about the behavior in the configuration file. This is done by adding the and "extensions" node to the configuration:

<extensions>
    <behaviorExtensions>
        <add name="CustomBehaviorElement"
             type="CustomBehaviorSample.MyCustomMessageFormatter, 
			Behavior, Version=1.0.0.0, 
			Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
</extensions>

This tells WCF where to find the bits for your custom behavior. The name you assign here will be used when we create the behavior configuration. The type attribute is the full name of the class with all the rest of the type information WCF needs to locate and load it. In your config file is it CRUCIAL that this all be on one, non broken line. I broke it here so it would be easier to read. Also remember that spelling counts. I spent about 25 minutes trying to figure out why this didn't work for me the first time, only to discover that I had misspelled the word "neutral."

So far, so good. The next step is creating the behavior configuration.

Do you remember last time when I said there were two type of behaviors? Service and Endpoint Behaviors. Well, trust me, I said it.

Anyway, since Service and Endpoint configurations need to be separated in our config file, this is where we need that information again. For the record, we created an Endpoint behavior, so our behavior configuration will look like this:

<behaviors>
    <endpointBehaviors>
        <behavior name="MyCustomEndpointBehavior">
            <CustomBehaviorElement/>
        </behavior>
    </endpointBehaviors>
</behaviors>
Let's contrast that with a behavior configuration for an out-of-the-box behavior:
<behaviors>
    <serviceBehaviors>
        <behavior name="MEXBehaviour">
            <serviceMetadata httpGetEnabled="true"/>
        </behavior>                
    </serviceBehaviors>
</behaviors>

Aside from the fact that one of these is an Endpoint behavior and one is a Service behavior, there aren't a lot of differences. We set a name so that we can reference the behavior elsewhere in our configuration. In our WCF-supplied MEX behavior we have a pre-defined configuration tag which supplies the configuration information for us. In the configuration for our custom behavior, we are doing the same thing, except that the behavior tag that we are using was defined by when we added the behavior type information in the behaviorExtensions section of the configuration.

The other difference we see is that we are setting a property of the MEX behavior; httpGetEnabled. We have the ability to add our own custom properties and we'll do this in the next post.

OK, we're almost there!

All that's left is to wire up are endpoint behavior configuration:

<endpoint address="HelloWCF" binding="wsHttpBinding" 
	contract="CustomBehaviorSample.IHelloWCF" 
          behaviorConfiguration="MyCustomEndpointBehavior"/>

And that's pretty much it. If we run it, we get the result we expect:

 See, it worked!

Easy peasy! But, that message is hard coded into our behavior, and I don't really like that. We'll fix that in the next post...

Print | posted on Saturday, March 01, 2008 10:29 AM

Feedback

# re: Making WCF "Behave" - Part Three

left by Brian at 3/21/2008 6:33 PM Gravatar
uhh.... I link to your right blog page now. But I am wondering if I should.

We need some non-technical posts!

# re: Making WCF "Behave" - Part Three

left by Tobias Manthey at 7/25/2008 11:43 AM Gravatar
Hi James,

thanks for your Example. I posted an example with walkthrough of a real world example on http://my-tech-talk.blogspot.com/2008/07/adding-flatwsdl-to-wcf-webservice.html

Cheers,
Tobias
Title  
Name
Email (never displayed)
Url
Comments   
Please add 3 and 7 and type the answer here: