Welcome to MSDN Blogs Sign in | Join | Help

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 = "http://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", "http://test", "test1");
proxy.Test();
((IContextChannel)proxy).AddAutoHeader("TestHeader2", "http://test", "test2");
proxy.Test();
proxy.Test();
((IContextChannel)proxy).RemoveAutoHeader("TestHeader1", "http://test");
proxy.Test();
factory.Close();
host.Close();
Console.ReadLine();
}
}

Next time: Pipe Properties

Published Friday, August 22, 2008 5:00 AM by Nicholas Allen
Filed under: ,

Comments

Friday, August 22, 2008 1:02 PM by Nicholas Allen's Indigo Blog

# Streaming Web Content

How do I deliver content from a WCF service as part of a web page? Web page content in this case typically

New Comments to this post are disabled
 
Page view tracker