Enumerating Behavior Extensions

As a follow up to my previous post “Is there an easy way to enumerate the bindings listed in configuration?”, today I will discuss how to enumerate one more of the WCF configuration extension points: behaviors.

Before I go further into this discussion, I need to define a few terms.

· Behavior – An element that defines how an endpoint or service acts (as opposed to communicates). A behavior configures service timeouts, for example.

· Runtime behavior – The behavior object used by the WCF runtime as part of the service and/or endpoint. When behavior appears without “runtime” specified this references the configuration object responsible for exposing the runtime behavior to the WCF configuration system.

· Configured behavior – An entry in the behaviors configuration collection that correlates to a named set of behaviors and their configuration.

·  “Available to my app” – Exists in the configuration merged view created when opening the application.config file associated with “my app”.

Now, without further ado, the discussion begins.

Unlike enumerating bindings listed in configuration, when I get asked about behaviors people really do want to enumerate these extensions. The only point of clarification lies around whether they want all extension elements available to an application, or just those used in a specific configuration. For the purpose of this posting, I will explore the following two scenarios:

1. Enumerate all of the behavior extensions available to my app

2. Enumerate all of the behaviors included in a configured behavior

Enumerate all of the behavior extensions available to my app

The scenario I hear most when I get this question involves creating a GUI application for dynamically defining services and/or endpoints that uses the configuration system to persist those definitions. You can think of the WCF configuration editor as an example of such an application, or a custom application scoped specifically to creating services and/or endpoints instead of managing the entire WCF configuration model. The solution I describe for this scenario actually accomplishes two things. First, it discovers all of the behavior configuration element names available to an application. Second, it examines each of the behaviors found and discovers the underlying runtime behavior associated with that configuration element.

Just like binding extensions, you find the behavior extensions registered under one of the three collections contained in the ‘extensions’ section of the ‘system.serviceModel’ section group. Specifically, the ‘behaviorExtensions’ collection contains all of the registered behavior extensions. Thus, enumerating all of the behavior extensions available to an application simply involves enumerating the entries in this collection. Each entry consists of two attributes; name and type. The name property corresponds to the xml element name that references this behavior. The type property corresponds to the type that knows how to deserialized the configuration XML for this behavior.

<configuration>

  <system.serviceModel>

    <extensions>

      <behaviorExtensions>

        <add name="clientCredentials" type="System.ServiceModel.Configuration.ClientCredentialsElement, System.ServiceModel, ..."/>

      </behaviorExtensions>

  </system.serviceModel>

</configuration>

 

The first part of this solution simply involves enumerating the entries in the ‘behaviorExtensions’ collection and capturing each entries' name.

The second part of this solution involves enumerating the entries in the extension collection and capturing each entries’ type. Since this type will implement the BehaviorExtensionElement base class, the solution can create an instance of the behavior extension type and cast it to the BehaviorExtensionElement. To facilitate enumerations like this, BehaviorExtensionElement contains a helper property (get only), BehaviorType, which returns the type of the underlying runtime behavior configured by this extension, which satisfies the second part of this solution.

Here is a quick bit of code that accomplishes both of these tasks and displays the information to the console:

static void EnumerateAllAvailableBehaviorExtensions()

{

    ExtensionsSection serviceModelExtensions = (ExtensionsSection)ConfigurationManager.GetSection("system.serviceModel/extensions");

    if (97 > Console.WindowWidth)

    {

        Console.WindowWidth = 97;

   }

    Console.WriteLine("{0,-22} : {1}",

        "Xml Element Name",

        "Underlying Behavior Type");

    foreach (ExtensionElement behaviorExtension in serviceModelExtensions.BehaviorExtensions)

    {

        BehaviorExtensionElement behaviorExtensionElement = (BehaviorExtensionElement)Activator.CreateInstance(Type.GetType(behaviorExtension.Type));

        Console.WriteLine("{0,-22} : {1}",

            behaviorExtension.Name,

            behaviorExtensionElement.BehaviorType.FullName);

    }

}

 

Enumerate all of the behaviors included in a configured behavior

When enumerating configured behaviors you need to understand the WCF configuration system segregates configured behaviors that act on services and those that act on endpoints. This explicit scoping reduces any errors with referencing a set of endpoint behaviors on a service and vice versa. Endpoint behaviors reside in the ‘endpointBehaviors’ collection contained within the ‘behaviors’ section in the ‘system.serviceModel’ section group. Service behaviors reside in the ‘serviceBehaviors’ collection that is a sibling to the ‘endpointBehaviors’ collection. In both cases, a configured behavior corresponds to a named collection of BehaviorExtensionElement objects.

<configuration>

  <system.serviceModel>

    <behaviors>

      <endpointBehaviors>

        <behavior name="myEndpointBehavior">

          <clientCredentials/>

        </behavior>

      </endpointBehaviors>

      <serviceBehaviors>

        <behavior name="myServiceBehavior">

          <serviceCredentials/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

Enumerating the configured behaviors simply involves enumerating the entries in the appropriate behaviors collection (e.g. ‘endpointBehaviors’ and/or ‘serviceBehaviors), capturing each entries name, and then enumerating the contained BehaviorExtensionElement objects. To help identify WCF configuration extension objects where consumed, the abstract base class for all WCF extension elements (ServiceModelExtensionElement) contains the helper property (get only) ConfigurationElementName. This returns the XML element name corresponding to a particular extensions element, and tracks back to that extension’s name attribute in the ‘extensions’ section registration. When enumerating configured behaviors for this scenario, my solution makes use of this property to list each behavior extension’s element name as well as the underlying runtime behavior type.

Here is a quick bit of code that accomplishes these tasks and displays the information to the console:

static void EnumerateConfiguredEndpointBehaviors()

{

    BehaviorsSection behaviors = (BehaviorsSection)ConfigurationManager.GetSection("system.serviceModel/behaviors");

    foreach (EndpointBehaviorElement endpointBehavior in behaviors.EndpointBehaviors)

    {

        Console.WriteLine("Behavior '{0}':", endpointBehavior.Name);

        foreach (BehaviorExtensionElement behaviorExtension in endpointBehavior)

        {

            Console.WriteLine("{0,-22} : {1}",

                behaviorExtension.ConfigurationElementName,

                behaviorExtension.BehaviorType.FullName);

        }

    }

}

static void EnumerateConfiguredServiceBehaviors()

{

    BehaviorsSection behaviors = (BehaviorsSection)ConfigurationManager.GetSection("system.serviceModel/behaviors");

    if (97 > Console.WindowWidth)

    {

        Console.WindowWidth = 97;

    }

    foreach (ServiceBehaviorElement serviceBehavior in behaviors.ServiceBehaviors)

    {

        Console.WriteLine("Behavior '{0}':", serviceBehavior.Name);

        foreach (BehaviorExtensionElement behaviorExtension in serviceBehavior)

        {

            Console.WriteLine("{0,-22} : {1}",

                behaviorExtension.ConfigurationElementName,

                behaviorExtension.BehaviorType.FullName);

        }

    }

}

 

I hope this sheds some light on the various methods of enumerating behaviors available to an application using the WCF configuration system.

Mark Gabarra

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm