We are often required to pass critical data to some or all of the calls to our service operations. Data such as user or security tokens, special parameters, time signatures, etc. It is not recommended to pass these kind of values as parameters of the calls, the best is to separate the business logic from the context data of our services.
Adding custom headers to the calls is in this case the best solution.
The whole operation is composed of four steps:
- Client
- Add header to the outgoing context message
- Call the operation
- Service
- Extract header data
- Execute operation and return result
The simplest way to add a custom header to a WCF call would be to manually attach it to each call’s OperationContext.
Inside the client, we assume we already added a reference to the service name, MyServiceRef.
The header can be added to the call by overloading the constructor of the MyServiceRef.MyServiceClient in a custom class.
public class MyService : MyServiceClient
{
//Init service and attach custom header
public MyService(string customHeader) : base()
{
MessageHeader header
= MessageHeader.CreateHeader(
HeaderId.HeaderName,
HeaderId.HeaderNS,
customHeader
);
OperationContextScope scope =
new OperationContextScope(this.InnerChannel);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
}
}
When calling asynchronously GetHeader() function of MyService asynchronously from the client application, it is critical to assign the event inside the using statement to keep the integrity of the call and therefore to correctly attach the custom header to the context, before the actual operation call.
//call service and attach the header
using (MyService client = new MyService(textBox1.Text))
{
client.GetHeaderCompleted +=
new EventHandler<MyServiceRef.GetHeaderCompletedEventArgs>
(client_GetHeaderCompleted); client.GetHeaderAsync();
}
Inside the WCF service, the extraction of the header from the current OperationContext can be done as following:
static string GetHeaderInfo()
{
System.ServiceModel.Channels.MessageHeaders headers =
OperationContext.Current.IncomingMessageHeaders;
return headers.GetHeader<string>(
HeaderId.HeaderName,
HeaderId.HeaderNS);
}
Headers are usually used to pass sensitive data, so to assure their integrity, I can think of a few things to recommend:
- if possible try to generate the content of the header inside the service (following a login function for example)
- try using at least a basic encryption system on the content of the header
Source code for this post is included here.
Adrian