Passing complex type through WCF header,The simple always work version.

3 minute read

Recently I tried to find a nice code sample for how to pass complex type through WCF, inside the header, meaning I want to send the client execution context to the server side.

All of the samples passes strings or uses custom header that needs to write and read the object manually, I didn't like it.

So I wrote one and it's working!
All you need is 2 classes, and one is just a factory for the other, very simple:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Text;

namespace debugniv.ComplexTypeOverWcf
{
class HeaderHandler : IDispatchMessageInspector, IClientMessageInspector
{
#region Implementation of IDispatchMessageInspector

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Read the complex type from header
var headerIndex = request.Headers.FindHeader(typeof(MyHeader).Name, typeof(MyHeader).Namespace);

if (headerIndex >= 0) // found!
{
var serializer = GenerateDataContractSerializer<MyHeader>();
var myHeader = request.Headers.GetHeader<MyHeader>(headerIndex, serializer);
// here you can do something with your header like push it to a global per request context.
}
return null;
}

public void BeforeSendReply(ref Message reply, object correlationState)
{
// nothing here
}

#endregion

#region Implementation of IClientMessageInspector

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var myHeader = GetMyHeader();
request.Headers.Add(myHeader);
}

public void AfterReceiveReply(ref Message reply, object correlationState)
{
// nothing to do here
}

#endregion

private DataContractSerializer GenerateDataContractSerializer<T>()
{
return new DataContractSerializer(typeof(T), typeof(T).Name, typeof(T).Namespace, GetKnownTypes());
}

private IEnumerable<Type> GetKnownTypes()
{
// here return all your types inside the header
yield return typeof(MyHeader);
yield return typeof(SubType);
}

private MessageHeader GetMyHeader()
{
var data = new MyHeader();
var serializer = GenerateDataContractSerializer<MyHeader>();
return MessageHeader.CreateHeader(data.GetType().Name, data.GetType().Namespace, data, serializer);
}


}

// this is the header
internal class MyHeader
{
public SubType InternalData { get; set; }
}

internal class SubType
{
}
}


The second thing you'll need is to attach this stuff to your service and proxy, here is one way to do this

using System;
using System.ServiceModel.Configuration;

namespace debugniv.ComplexTypeOverWcf
{
public class HeaderExtensionElement : BehaviorExtensionElement
{

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

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

In you config file add the following



Updated:

Comments