Setting Configuration Defaults with Nameless Elements in WCF 4

This is my second post about Beta 1 features in WCF 4.0 after introducing the DataContractResolver.

 

Beta 1 introduces a new way of using WCF configuration. It’s now possible to specify a default for bindings, service behaviors, endpoint behaviors, and standard endpoints.

 

Here’s a concrete example to illustrate my point. Suppose you have the following configuration:

 

<configuration>

  <system.serviceModel>

    <services>

      <service name="Service.EchoService" behaviorConfiguration="ServiceBehavior">

        <endpoint address ="" binding="basicHttpBinding" contract="Service.IEcho"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

      <service name="Service.HelloWorldService" behaviorConfiguration="ServiceBehavior">

        <endpoint address ="" binding="basicHttpBinding" contract="Service.IHelloWorld"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="ServiceBehavior">

          <serviceMetadata httpGetEnabled="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

Notice how you have two services referencing the same service behavior. Well, this is now equivalent to the following:

 

<configuration>

  <system.serviceModel>

    <services>

      <service name="Service.EchoService">

        <endpoint address ="" binding="basicHttpBinding" contract="Service.IEcho"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

      <service name="Service.HelloWorldService">

        <endpoint address ="" binding="basicHttpBinding" contract="Service.IHelloWorld"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <serviceMetadata httpGetEnabled="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

Both services got the serviceMetadata behavior, even though neither one specified a behavior Configuration. Services that do not specify a behaviorConfiguration now receive the behavior element that is specified without a name. In these cases, not having a name specified or not having a behaviorConfiguration specified is semantically equivalent to having both assigned to the empty string. So again, both of the configurations listed above are equivalent to:

 

<configuration>

  <system.serviceModel>

    <services>

      <service name="Service.EchoService" behaviorConfiguration="">

        <endpoint address ="" binding="basicHttpBinding" contract="Service.IEcho"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

      <service name="Service.HelloWorldService" behaviorConfiguration="">

        <endpoint address ="" binding="basicHttpBinding" contract="Service.IHelloWorld"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="">

          <serviceMetadata httpGetEnabled="True" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

This works in pretty much the same way for bindings, endpoint behaviors, and standard endpoints as well. So,

 

<configuration>

  <system.serviceModel>

    ...

    <bindings>

      <basicHttpBinding>

        <binding maxReceivedMessageSize="16777216" />

      </basicHttpBinding>

    </bindings>

  </system.serviceModel>

</configuration>

 

Would mean that any endpoint that is specified with binding="basicHttpBinding" bindingConfiguration="" or just binding="basicHttpBinding" would get a maxReceivedMessageSize of 16 MB by default.

 

Note that defaults entirely stop applying if you specify your behaviorConfiguration, bindingConfiguration, or endpointConfiguration as being anything other than the empty string. It is possible, however, to inherit defaults from a configuration that is higher up in the configuration hierarchy. So a default set at the machine.config level would apply to all relevant, unspecified configuration elements on that machine.

 

While this may seem like a minor feature, it significantly increases the potential of another new configuration feature in WCF 4.0: services configured without a <service> tag. I’ll discuss that in more depth in a future post.