Passing complex type through WCF header,The simple always work version.
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:
The second thing you'll need is to attach this stuff to your service and proxy, here is one way to do this
In you config file add the following
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
Chen, cant see the section following "In you config file add the following" ..... ?
ReplyDeleteFrom the page source:
ReplyDeleteIn you config file add the following:
<extensions>
<behaviorExtensions>
<add
name="customEndpointBehavior"
type="your extension type name"/>
</behaviorExtensions>