Passing complex type through WCF header,The simple always work version.
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
Comments