Behavior Merge in WCF 4.0 Configuration

One of the brand new configuration features you can find in the Beta 2 release of .NET 4.0 is the ability to merge behaviors in the configuration hierarchy. This should make it easier to manage behaviors when you want a set of common behaviors to be used consistently. To illustrate how this works, let’s say you have the following virtual directory layout hosted in IIS:

 

~\Web.config

~\Service.svc

~\Child\Web.config

~\Child\Service.svc

                               

And let’s say your ~\Web.config looks like this:

 

<configuration>

  <system.serviceModel>

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <serviceDebug includeExceptionDetailInFaults="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

And that your child Web.config at ~\Child\Web.config looks like this:

 

<configuration>

  <system.serviceModel>

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <serviceMetadata httpGetEnabled="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

Then, the service at ~\Child\Service.svc will behave as though it had both the serviceDebug and the serviceMetadata behaviors. The service at ~\Service.svc will only have the serviceDebug behavior though. What has happened is that the two behavior collections with the same name (in this case the empty string) have had their behavior elements merged.

 

Apart from adding behaviors to a behavior collection, you can also clear behavior collections by using the <clear> tag, and remove individual behaviors from the collection by using the <remove> tag. So both of these ~\Child\Web.config files:

 

<configuration>

  <system.serviceModel>

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <remove name="serviceDebug"/>

          <serviceMetadata httpGetEnabled="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

And

 

<configuration>

  <system.serviceModel>

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <clear/>

          <serviceMetadata httpGetEnabled="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

Would result in the child service having only the serviceMetadata behavior, and not the serviceDebug behavior.

 

A few notes:

 

· This works not only for nameless behavior collections as shown above, but also for named behavior collections. So if you had:

<serviceBehaviors>

<behavior name="Foo">

At both the root Web.config and the child Web.config, the child service would have the behaviors merged for both of the behavior collections named “Foo”.

 

· Behavior merge works in the IIS hosting environment, in which Web.config files merge hierarchically with the root Web.config file and machine.config. But it also works in the application environment, where machine.config can merge with the App.config file.

 

· Behavior merge applies to both endpoint behaviors and service behaviors in configuration.

 

· If a child behavior collection contains a behavior that’s already present in the parent behavior collection, the child behavior overrides the parent one. So if a parent behavior collection had <serviceMetadata httpGetEnabled="False" /> and a child behavior collection had <serviceMetadata httpGetEnabled="True" />, the child behavior would override the parent behavior in the behavior collection and httpGetEnabled would be “true”.

Comments

  • Anonymous
    December 23, 2009
    I set the httpGetEnabled a False value in ~Web.config, and gave a True value to the httpGetEnabled in the ~ChildWeb.config,but i got a message - Metadata publishing for this service is currently disabled. To your this article,it's not expected to get this result. And to my testing ,the results in VS2008 SP1 and VS2010 Beta 2  are same!

  • Anonymous
    December 23, 2009
    and where can i get the demo which you illustrated? look forward to your answer!

  • Anonymous
    December 28, 2009
    Hi Jack, what you described should work. But here are some things you may want to check:

  1. Are you checking the ~Service.svc or the ~ChildService.svc. In your case, metadata publishing should be disabled for the parent but enabled for the child.
  2. Are you sure that IIS is running with the 4.0 version of the framework? It's possible it's running with an earlier version. Sometimes, removing the IIS feature and re-adding it fixes this issue.
  3. Are you using tagless services? Behavior collections will only merge if they have the same name. Nameless behavior collections will merge together. But nameless behavior collections will only be used if you don't specify a behaviorConfiguration on your service element or if you use tagless services. You can find a sample of this at work by downloading the WF and WCF 4.0 samples for Beta2 at http://www.microsoft.com/downloads/details.aspx?FamilyID=35ec8682-d5fd-4bc3-a51a-d8ad115a8792&displaylang=en and going to WF_WCF_SamplesWCFBasicServicesConfigHierarchicalModelCS under the extracted samples. Hope that helps.
  • Anonymous
    January 03, 2010
    thanks, i found the problem with your answer : i created my  demo with the default configuration,so the config contained services with tags, the problem fixed after i removed the service element in the config. look forward to your more exciting articles.