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