Client Additional Parameters using Custom Headers in WCF

When building Service communication applications using Windows Communication Foundation, we often come to a situation where we have multiple clients communicating with WCF Service and we need to pass additional parameters from client to service. This may be due to number of reasons such as sharing a unique customer ID to identify certain elements for that particular client. In such scenarios, for every communication between client and server, you need this unique ID to treat each client accordingly.

Client-Server-Customer-Id-Parameter-WCF

In a typical disconnected environment over the internet you need to pass such data on each call to service and of course passing in each Service Method or Operation Call is confusing and not appropriate.

A good Solution is to pass additional parameters in SOAP headers utilizing with the help of Custom headers in WCF. A SOAP envelope contains a header and a body. Method call and its parameters are transformed to SOAP body whereas SOAP header usually contains application-specific information (like authentication etc.)

 image

A simple way to achieve this in WCF is to add MessageHeader in your proxy class as in code snippet below:

public partial class TestServiceClient : ClientBase<Client.ServiceProxy.ITestService>, Client.ServiceProxy.ITestService
{
    public TestServiceClient()
    {
        var header = new MessageHeader<string>("Customer Unique Id: 12345");
        var untyped = header.GetUntypedHeader("Identity", "http://www.adilmughal.com");
        OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
    } 
    //Other constructors and Service Method Calls
}

However this is really NOT a suitable approach as if you would be generating proxy using svcutil.exe or using Visual Studio then it will replace your proxy code.

A Better Solution to solve this problem is to utilize custom behavior extension in WCF to pass additional parameters in SOAP Message header. Following are the steps required on client:

1) Implement IClientMessageInspector to create custom message inspector

public class MyMessageInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply,object correlationState)
    {
       Console.WriteLine("SOAP Response: {0}", reply.ToString());
    }
        
    public object BeforeSendRequest(ref Message request,IClientChannel channel)
    {
       var header = new MessageHeader<string>("Customer Unique Id: 12345");
       var untyped = header.GetUntypedHeader("Identity", "http://www.adilmughal.com");
       request.Headers.Add(untyped);Console.WriteLine("SOAP Request: {0}", request.ToString());
       return null;
    } 
}

2) Create a custom behavior class implementing IEndPointBehavior and BehaviorExtensionElement. Then add the custom message inspector in runtime in ApplyClientBehavior method as shown in code snippet below:

public class CustomBehavior : BehaviorExtensionElement, IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

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

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

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    public override Type BehaviorType
    {
        get {   return typeof(CustomBehavior);  }
    }   

    protected override object CreateBehavior()
    {
        return new CustomBehavior();
    }
}

3) Finally, register behavior in .config under

<behaviors>
 <endpointBehaviors>
 <behavior>
 <customInspector />
 </behavior>
 </endpointBehaviors>
</behaviors>
<extensions>
 <behaviorExtensions>
 <add name="customInspector" type="Client.CustomBehavior, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
 </behaviorExtensions>
</extensions>

That is all you have to do on client end to pass additional parameter in SOAP header using Custom Behavior in WCF.

To retrieve parameter passed in header on server side, you need to use OperationContext object

MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string customParameter = headers.GetHeader&lt;string&gt;("Identity", "http://www.adilmughal.com");
return string.Format("You entered: {0}", customParameter);

This would achieve the objective. Following is the detail of SOAP Envelope:

SOAP Request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/ITestService/GetDataAction>
<Identity xmlns="http://www.adilmughal.com">Customer Unique Id: 12345Identity>
s:Header>
<s:Body>
<GetData xmlns="http://tempuri.org/">
<value>123value>
GetData>
s:Body>
SOAP Response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<GetDataResponse xmlns="http://tempuri.org/">
<GetDataResult>You entered: Customer Unique Id: 12345GetDataResult>
GetDataResponse>
s:Body>
s:Envelope>

In this post we saw how to create custom SOAP header in WCF to pass parameter from client to server using WCF behavior extension. Hope this helps.




  • Thanks for this nice post..

  • @Usama Thanks for the compliment!

  • Dan

    This was very helpful! Thanks so much. I’ve read through about 20 different ways to do this today and this was the only one I could get to work.

    I used silverlight, so to actually add the custom endpoint behavior I had to use this: http://silverlightedweb.blogspot.com/2011/08/adding-custom-endpoint-behavior-at.html

  • @Dan: Glad to know it helped. For Silverlight, I have published another blog post that may be of any help to you.
    http://www.adilmughal.com/2011/10/wcf-custom-header-with-silverlight.html

  • This part does not work for me .IT does not recognise customInspector .

  • @Jitendar: Can you share some details? or email me via contact form?

  • Guest

    Thanks a lot! This solved exactly my problem, great article!

  • I have the same problem. In the app.config file the ” ” does not work. It says behavior has invalid child element. I have a winforms app and it is done in VB.

  • I’ve the same problem as Jitender and Riaan:

    The element ‘behavior’ has invalid child element ‘customInspector’. List of possible elements expected: ‘clientVia, callbackDebug, callbackTimeouts, clear, clientCredentials, transactedBatching, dataContractSerializer, dispatcherSynchronization, remove, synchronousReceive, enableWebScript, webHttp, endpointDiscovery, soapProcessing’.

    Web.config

  • @Utopiq and Riaan: Can you please share some sample code?
    Are you using .NET framework client profile or full one?

  • @jitendar: Your provided email address is bouncing back. Please provide alternative.

  • Anonymous

    Hi Adil, if you have a solution for utopiq, Jitender, and Riaan could you please post it? I have the same problem in web.config.

    The element ‘behavior’ has invalid child element ‘customInspector’. List of possible elements expected: ‘clientVia, callbackDebug, callbackTimeouts, clear, clientCredentials, transactedBatching, dataContractSerializer, dispatcherSynchronization, remove, synchronousReceive, enableWebScript, webHttp, endpointDiscovery, soapProcessing’.

  • Try …

  • Anonymous

    I have a .net 4.0 web forms application consuming a service. I got the same error about the web.config, the customInspector was not a recognized element inside

    I used the silverlight solution instead, and registered the behavior programmatically as per this post:
    http://www.adilmughal.com/2011_10_01_archive.html

    ServiceProxy.TestServiceClient proxy = new ServiceProxy.TestServiceClient();proxy.Endpoint.Behaviors.Add(new CustomBehavior());

    And this solved my problem

  • Thanks for sharing your experience and resolution…

  • nice article. thanks for sharing

  • Nandu -: can u please attach demo project of this…..

  • Dileep Reddy

    Hi Adil,
    I get the following error after modifying the web.config file as you said.
    The type ‘Client.CustomBehavior, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ registered for extension ‘custom Inspector’ could not be loaded.
    Can you please share the code sample.
    My email id : dileepkrso@gmail.com