Freigeben über


AutoHeader Extension

I frequently get asked how to add a header to every outgoing request so I wrote up a quick reusable approach. This adds some extension methods to the IContextChannel class for working with auto-added headers. The headers are stored between calls in an IExtension.

 public static class AutoHeaderExtension
{
   class AutoHeaderContextExtension : Dictionary<XName, MessageHeader>, IExtension<IContextChannel>
   {
      public void Attach(IContextChannel owner)
      {
      }

      public void Detach(IContextChannel owner)
      {
      }
   }

   public static void AddAutoHeader(this IContextChannel proxy, string name, string ns, object value)
   {
      AutoHeaderContextExtension extension = proxy.Extensions.Find<AutoHeaderContextExtension>();
      if (extension == null)
      {
         extension = new AutoHeaderContextExtension();
         proxy.Extensions.Add(extension);
      }
      extension[XName.Get(name, ns)] = MessageHeader.CreateHeader(name, ns, value);
   }

   public static IEnumerable<MessageHeader> GetAutoHeaders(this IContextChannel proxy)
   {
      AutoHeaderContextExtension extension = proxy.Extensions.Find<AutoHeaderContextExtension>();
      if (extension == null)
      {
         return Enumerable.Empty<MessageHeader>();
      }
      return extension.Values;
   }

   public static void RemoveAutoHeader(this IContextChannel proxy, string name, string ns)
   {
      AutoHeaderContextExtension extension = proxy.Extensions.Find<AutoHeaderContextExtension>();
      if (extension != null)
      {
         extension.Remove(XName.Get(name, ns));
      }
   }
}

If you combine that with a message inspector that adds the headers on to each message, then you get a collection of headers that are added to every outgoing request.

 public class AutoHeaderMessageInspectorBehavior : IEndpointBehavior
{
   class AutoHeaderMessageInspector : IClientMessageInspector
   {
      public void AfterReceiveReply(ref Message reply, object correlationState)
      {
      }

      public object BeforeSendRequest(ref Message request, IClientChannel channel)
      {
         foreach (MessageHeader header in channel.GetAutoHeaders())
         {
            request.Headers.Add(header);
         }
         return null;
      }
   }

   public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
   {
   }

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

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

   public void Validate(ServiceEndpoint endpoint)
   {
   }
}

Here's an example using this extension.

 [ServiceContract]
public interface IService
{
   [OperationContract(Action="*")]
   void Test();
}

public class Service : IService
{
   public void Test()
   {
      Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage);
   }
}

class Program
{
   static void Main(string[] args)
   {
      string address = "localhost:8000/";
      Binding binding = new BasicHttpBinding();
      ServiceHost host = new ServiceHost(typeof(Service), new Uri(address));
      host.AddServiceEndpoint(typeof(IService), binding, "");
      host.Open();
      ChannelFactory<IService> factory = new ChannelFactory<IService>(binding);
      factory.Endpoint.Behaviors.Add(new AutoHeaderMessageInspectorBehavior());
      factory.Open();
      IService proxy = factory.CreateChannel(new EndpointAddress(address));
      proxy.Test();
      ((IContextChannel)proxy).AddAutoHeader("TestHeader1", "test", "test1");
      proxy.Test();
      ((IContextChannel)proxy).AddAutoHeader("TestHeader2", "test", "test2");
      proxy.Test();
      proxy.Test();
      ((IContextChannel)proxy).RemoveAutoHeader("TestHeader1", "test");
      proxy.Test();
      factory.Close();
      host.Close();
      Console.ReadLine();
   }
}

Next time: Pipe Properties

Comments

  • Anonymous
    August 22, 2008
    How do I deliver content from a WCF service as part of a web page? Web page content in this case typically