Adding data to WCF headers

As I’ve covered this subject using WSE3, now to look at adding an SSO token to a WCF header.

Configuration

In your App.config you’ve probably got something like

<system.serviceModel>
   <client configSource="Config\servicemodel-client-config.xml" />
   <bindings configSource="Config\servicemodel-bindings-config.xml" />
</system.serviceModel>

We’re going to add two more configuration files, as follows

<system.serviceModel>
   <client configSource="Config\servicemodel-client-config.xml" />
   <bindings configSource="Config\servicemodel-bindings-config.xml" />
   <!-- Additions -->
   <behaviors configSource="Config\servicemodel-behaviors-config.xml" />
   <extensions configSource="Config\servicemodel-extensions-config.xml" />
</system.serviceModel>

As the names suggest, these file will include the config for behaviors and extensions.

Let’s take a look at the servicemodel-behaviors-config.xml first

<?xml version="1.0" encoding="utf-8" ?>
<behaviors>
   <endpointBehaviors>
      <behavior name="serviceEndpointBehaviour">
         <ssoEndpointBehaviorExtension />
         <!-- insert any other behavior extensions here -->
      </behavior>
   </endpointBehaviors>
</behaviors>

Now we need to actually define what implements ssoEndpointBehaviorExtension. So in the servicemodel-extensions-config.xml configuration, we might have something like the following

<?xml version="1.0" encoding="utf-8" ?>
<extensions>
   <behaviorExtensions>
      <add name="ssoEndpointBehaviorExtension"
            type="SsoService.SsoEndpointBehaviorExtensionElement, SsoService"/>
      <!-- insert other extensions here -->
   </behaviorExtensions>
</extensions>

So as we can see, the ssoEndpointBehaviorExtension behavior is associated with the SsoService assembly and the type SsoEndpointBehaviorExtensionElement.

Implementing the behavior/extension

Unlike WSE3 we do not need to use an attribute to associate the extension with a service call.

Let’s start by looking at the SsoEndpointBehaviorExtensionElement behavior extension.

public class SsoEndpointBehaviorExtensionElement : BehaviorExtensionElement
{
   public override Type BehaviorType
   {
      get { return typeof(SsoEndpointBehavior); }
   }
   
   protected override object CreateBehavior()
   {
      return new SsoEndpointBehavior();
   }
}

The code above relates to the actual extension element, so really just creates the actual behavior when required. Here’s the SsoEndpointBehavior.

public class SsoEndpointBehavior : IEndpointBehavior
{
   public void AddBindingParameters(ServiceEndpoint endpoint, 
                 BindingParameterCollection bindingParameters)
   {
   }

   public void ApplyClientBehavior(ServiceEndpoint endpoint, 
                 ClientRuntime clientRuntime)
   {
      clientRuntime.MessageInspectors.Add(new SsoMessageInspector());
   }

   public void ApplyDispatchBehavior(ServiceEndpoint endpoint, 
                 EndpointDispatcher endpointDispatcher)
   {
   }

   public void Validate(ServiceEndpoint endpoint)
   {
   }
}

This code simply adds the inspector to the message inspector. Finally let’s look at the code that actual intercepts the send requests to add the SSO token to the header.

public class SsoMessageInspector : IClientMessageInspector
{
   public object BeforeSendRequest(ref Message request, IClientChannel channel)
   {
      request.Headers.Add(MessageHeader.CreateHeader("ssoToken", 
              String.Empty, 
              SsoManager.TokenString);
      return null;
   }

   public void AfterReceiveReply(ref Message reply, object correlationState)
   {
   }
}

In the above code, we create an addition to the message header, with the name “ssoToken” followed by any namespace and then the value we wish to store with the header item. In this case our SSO token.