Handling data in WCF headers (service-side)

So my previous post looked at adding data into the headers of the WCF service calls from the client-side perspective.

Ofcourse for this to be of any use we need the service to handle the extraction of this header data. So this post is mean’t to cover the basics of this. First we need to create the extension, so we inherit from BehaviorExtensionElement (just as we did on the client)

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

Now we need to create an implementation of the IServiceBehavior (on the client this is the IEndpointBehavior)

public class SecurityTokenServiceBehaviour : IServiceBehavior
{
   public void Validate(ServiceDescription serviceDescription, 
                        ServiceHostBase serviceHostBase)
   {
   }

   public void AddBindingParameters(ServiceDescription serviceDescription, 
                         ServiceHostBase serviceHostBase, 
                         Collection<ServiceEndpoint> endpoints, 
                         BindingParameterCollection bindingParameters)
   {
   }

   public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
                         ServiceHostBase serviceHostBase)
   {
      foreach(ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
      {
         foreach(EndpointDispatcher epd in cd.Endpoints)
         {
            epd.DispatchRuntime.MessageInspectors.Add(new SecurityTokenMessageInspector());
         }
      }
   }
}

and finally we implement an IDispatchMessageInspector (on the client this would be the IClientMessageInspector)

public class SecurityTokenMessageInspector : IDispatchMessageInspector
{
   public object AfterReceiveRequest(ref Message request, 
                     IClientChannel channel, 
                     InstanceContext instanceContext)
   {
      return null;
   }

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

Okay so we’ve got all the code in place but now we need to tie this into WCF using the configuration (ofcourse if you prefer you can do this in code).

Just as we need to do in the client, we need to register the extension in an extensions element and again as per the client we then need to link the behaviour to the extension, see the App.config for this service below

<system.serviceModel>
   <behaviors>
      <serviceBehaviors>
         <behavior name="MyBehavior">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="true" />
            <!--our extension -->
            <securityTokenExtension /> 
         </behavior>
      </serviceBehaviors>
   </behaviors>
   <services>
      <service behaviorConfiguration="MyBehavior" name="SimpleService.MyService">
        <endpoint address="MyService" binding="basicHttpBinding"
          bindingConfiguration="" contract="SimpleService.IMyService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:9095/" />
          </baseAddresses>
        </host>
      </service>
   </services>
   <extensions>
      <behaviorExtensions>
        <add name="securityTokenExtension" 
           type="SimpleService.SecurityTokenEndpointBehaviourExtensionElement, SimpleService" />
      </behaviorExtensions>
   </extensions>
</system.serviceModel>

Finally, how do we get the value stored in the header on the service ?

The following code shows how we extract the value from the header named “myToken”, the generic argument shown in the method call GetHeader represents the type we expect the data to be.

public object AfterReceiveRequest(ref Message request, 
                  IClientChannel channel, 
                  InstanceContext instanceContext)
{
   int idx = request.Headers.FindHeader("myToken", String.Empty);
   if(idx >= 0)
   {
      Console.WriteLine(String.Format("Header value: {0}", 
                       request.Headers.GetHeader<string>(idx));
   }
   return null;
}