Paolo Pialorsi - Bridge The Gap!

Living in a Service Oriented World

Handling custom SOAP headers via WCF Behaviors

A few days ago a customer of mine asked me how to define a WCF behavior to add a custom SOAP Header to sent/received messages.

The solution is not so far from what I've shown in the previous "Writing a WCF Message Inspector" post. In fact one way of working is to define a custom message inspector that writes/reads the custom SOAP Header.

So first of all we need a SOAP Header. Here is the code to define a custom header to handle a random key (as a Guid) injected in every request sent from the consumer to the service:

public class CustomHeader : MessageHeader
{
    private String _key;

    public String Key
    {
        get
        {
            return (this._key);
        }
    }

    public CustomHeader(String key)
    {
        this._key = key;
    }

    public override string Name
    {
        get { return (CustomHeaderNames.CustomHeaderName); }
    }

    public override string Namespace
    {
        get { return (CustomHeaderNames.CustomHeaderNamespace); }
    }

    protected override void OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, MessageVersion messageVersion)
    {
        // Write the content of the header directly using the XmlDictionaryWriter
        writer.WriteElementString(CustomHeaderNames.KeyName, this.Key);
    }

    public static CustomHeader ReadHeader(XmlDictionaryReader reader)
    {
        // Read the header content (key) using the XmlDictionaryReader
        if (reader.ReadToDescendant(CustomHeaderNames.KeyName, CustomHeaderNames.CustomHeaderNamespace))
        {
            String key = reader.ReadElementString();
            return (new CustomHeader(key));
        }
        else
        {
            return null;
        }
    }

}

public static class CustomHeaderNames
{
    public const String CustomHeaderName = "CustomHeader";

    public const String KeyName = "Key";

    public const String CustomHeaderNamespace = "http://schemas.devleap.com/CustomHeader";

}

As you can see it is a type inheriting from MessageHeader class. Notice the OnWriteHeaderContents override, which is invoked by WCF infrastructure to serialize the SOAP Header, and the ReadHeader static method that we will use later.

Such a SOAP Header need to be added by the consumer and read by the service. To do this we need a MessageInspector like the following one:

public class CustomMessageInspector : IDispatchMessageInspector, IClientMessageInspector
{
    #region Message Inspector of the Service

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        // Look for my custom header in the request
        Int32 headerPosition = request.Headers.FindHeader(CustomHeaderNames.CustomHeaderName, CustomHeaderNames.CustomHeaderNamespace);

        // Get an XmlDictionaryReader to read the header content
        XmlDictionaryReader reader =
request.Headers.GetReaderAtHeader(headerPosition);

        // Read it through its static method ReadHeader
        CustomHeader header = CustomHeader.ReadHeader(reader);

        // Add the content of the header to the IncomingMessageProperties dictionary
      
OperationContext.Current.IncomingMessageProperties.Add("key", header.Key);

        return null;
    }

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

    #endregion

    #region Message Inspector of the Consumer

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        // Prepare the request message copy to be modified
        MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
        request = buffer.CreateMessage();

        // Simulate to have a random Key generation process
        request.Headers.Add(new CustomHeader(Guid.NewGuid().ToString()));

        return null;
    }

    #endregion
}

As you can see from the code sample above, we use the IClientMessageInspector implementation to handle the addition of the header in the consumer-side code, while we use the IDispatchMessageInspector on the service side, to extract the header. It is interesting the FindHeader method of the MessageHeaders collection, as well as the method GetReaderAtHeader, provided by the same collection of SOAP Headers. The result of this last method is an XmlDictionaryReader that we use to read our custom header content, through the ReadHeader static method we've already introduced.

The service will be able to read the Key provided throught the custom SOAP header simply querying the IncomingMessageProperties dictionary:

OperationContext.Current.IncomingMessageProperties["key"]

Of course this custom MessageInspector needs to be plugged into the WCF pipeline using a custom behavior like the following one:

[AttributeUsage(AttributeTargets.Class)]
public class CustomBehavior : Attribute, IEndpointBehavior
{
    #region IEndpointBehavior Members

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
        CustomMessageInspector inspector = new CustomMessageInspector();
        clientRuntime.MessageInspectors.Add(inspector);
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        ChannelDispatcher channelDispatcher = endpointDispatcher.ChannelDispatcher;
        if (channelDispatcher != null)
        {
            foreach (EndpointDispatcher ed in channelDispatcher.Endpoints)
            {
                CustomMessageInspector inspector = new CustomMessageInspector();
                ed.DispatchRuntime.MessageInspectors.Add(inspector);
            }
        }
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    #endregion
}

We also need an ExtensionElement to configure the behavior:

public class CustomBehaviorExtensionElement : BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new CustomBehavior();
    }

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

At last we can configure in the .config file of our service and consumer the behavior. Here is the service side configuration:

<system.serviceModel>

  <extensions>
    <behaviorExtensions>
      <add name="customBehavior" type="DevLeap.WCF.Behaviors.Extensions.CustomBehaviorExtensionElement, DevLeap.WCF.Behaviors.Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>

<services>
  <service name="DevLeap.WCF.Behaviors.Services.ServiceOne" behaviorConfiguration="serviceBehavior">
    <endpoint
     address="net.tcp://localhost:35001/ServiceOne/"
     binding="netTcpBinding"
     contract="DevLeap.WCF.Behaviors.Contracts.IServiceOne"
    behaviorConfiguration="endpointBehavior" />
  </service>
</services>

<behaviors>
  <endpointBehaviors>
    <behavior name="endpointBehavior">
     
<customBehavior />
    </behavior>
  </endpointBehaviors>

  </behaviors>

</system.serviceModel>

And here is the configuration of the consumer-side:

<system.serviceModel>

    <extensions>
      <behaviorExtensions>
        <add name="customBehavior" type="DevLeap.WCF.Behaviors.Extensions.CustomBehaviorExtensionElement, DevLeap.WCF.Behaviors.Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>

    <client>
            <endpoint name="serviceOneEndpoint"
                address="net.tcp://localhost:35001/ServiceOne/"
                binding="netTcpBinding"
                contract="DevLeap.WCF.Behaviors.Contracts.IServiceOne"
                behaviorConfiguration="serviceOneBehavior" />
        </client>

    <behaviors>
      <endpointBehaviors>
        <behavior name="serviceOneBehavior">
          <customBehavior />
        </behavior>
      </endpointBehaviors>
    </behaviors>

</system.serviceModel>

That's all! Enjoy your custom SOAP header defining infrastructural protocols, but don't forget to check the wide range of WS-* specifications before inventing your own :-) ...

Posted: Feb 25 2008, 11:13 AM by paolopia | with 65 comment(s) |
Filed under: , ,

Comments

Paolo Pialorsi said:

Ho appena postato un articolo che spiega come creare dei behavior personalizzati in WCF, per aggiungere

# February 25, 2008 5:14 AM

header key string said:

Pingback from  header key string

# April 2, 2008 3:47 PM

Tony said:

Hello Paolo Pialorsi,

Thanks for the excellent piece of code. I have been trying for several days to make this work.

However, I am having bit difficulty in implementing the same using code instead of the configuration file. Do you have any sample code to replace the above config sections?

- Tony

# April 29, 2008 3:05 PM

Breezback said:

Hey,

Any code avail to download?

Please post me update: ilan_levy at msn.com

# May 3, 2008 12:09 PM

paolopia said:

x Tony: you simply need to add your custom behavior via code using the ServiceHost instance and adding it to the Behaviors collection of the Description property.

x Breezback: actually I don't have a download available from here, may be in the future. However following my step by step instructions you could be able to reproduce it.

# May 23, 2008 2:54 AM

Tony John said:

I have created a simple client server sample based this article. You can download it here - www.dotnetspider.com/.../19314-Client-server-sample-using-WCF-net-tcp-binding.aspx

- Tony John

# June 30, 2008 6:41 PM

Kris-I said:

@Tony John

I'm trying to update you sample by add a database a DAL (library in the host solution) but it's not working fine

# August 25, 2008 10:40 AM

jdanforth said:

Thanks a million, I've been at this all evening. This is worth a blog post :)

# October 23, 2008 2:29 PM

MrAdvani said:

Paolo, This is excellent work, thanks for posting it.

I haven't tried your code as yet, but from going through it I have a question -

By introducing a custom soap header in this way will it be included as part of the WSDL too?

Thanks

Ravi

# November 6, 2009 2:04 PM

Tavi said:

Paolo

Thanks for excellent post

Just i want to add an additional element to existing SOAP Header...like clientID

Is it possible?

If possible where exactly i need to change in web.config file?

# December 23, 2009 6:18 AM

Stephen said:

Any way to add the header without IClientMessageInspector and IEndpointBehavior?  Compact Framework does not have those....

# January 13, 2010 5:14 PM

Adam said:

This is a great article.  Very clear, but I'd really like to see an example implements the IContractBehavior instead of IEndpointBehavior.  All the example I can find use the EndpointBehavior.  The problem is that you can't attach the ContractBehavior in configuration, and I'm having a hard time knowing exactly how to add the behavior to the behaviors collection.

My situation is that I already have a custom header defined on the Service, so I don't think I can inherit from IContractBehaviorAttribute and simply decorate with an attribute?  Tell me if I'm wrong.  What are my options in this situation.  I only want the header added on one particular contract and not everything in the endpoint.

Thanks,

Adam

# April 23, 2010 6:26 PM

PasserBy said:

Cool article you got here. I'd like to read a bit more about that theme. The only thing I would like to see on that blog is some pics of some gadgets.

Jeff Kripke

<a href="www.jammer-store.com/">cell phone jammer</a>

# July 9, 2010 5:53 AM

exclusive escorts said:

It was certainly interesting for me to read that blog. Thanx for it. I like such themes and anything that is connected to them. I definitely want to read a bit more soon. BTW, rather nice design this site has, but don’t you think it should be changed once in a few months?

John Pingtown

# July 14, 2010 5:31 PM

exclusive escorts said:

Truly cool site to track it to my thinking. By the way, why don't you submit it to social bookmarking sites? That should bring much traffic to this article.

# July 24, 2010 3:15 AM

London escorts spanish said:

I definitely want to read a bit more on this blog soon. By the way, rather good design that blog has, but don’t you think design should be changed once in a few months?

Katie Funweather

# July 30, 2010 3:24 PM

russian escort geneva said:

Don't stop posting such articles. I like to read articles like this. BTW add more pics :)

# September 3, 2010 2:07 AM

Ganesh said:

Thanks Tony and Paolo :

Your article and sample helped me a lot today. I was looking for exactly the same functionality!!

# September 14, 2010 9:28 AM

Kiev escort agency said:

Cool story you got here.

It would be great to read something more concerning that theme.

Thnx for posting this material.

With best regards Lina!

# September 19, 2010 2:33 AM

dror said:

I tougth its working , but now I think is not working sample.

<service name="DevLeap.WCF.Behaviors.Services.ServiceOne" behaviorConfiguration="serviceBehavior">

is not legal.

I remove it, but still , my custom behavior on the server is not invoked.

# October 20, 2010 7:55 AM

football said:

Hello! I love watching football and I loved your blog as well.

# May 30, 2011 11:50 PM

Some useful WCF related links said:

Pingback from  Some useful WCF related links

# July 8, 2011 8:29 AM

Ebonie Figuroa said:

I really love some of your posts, can i take component of your articles to my own web log? thank you.

# July 9, 2011 6:50 PM

pregnancy-symptoms said:

Pregnancy Symptoms taycsbhmm eoqreuae f cekwwvpkj vafmfoiqu cvhd btq xx                                                                        

znmvyxrzy yenivh kwa enfcnkuvz dhcfuc ijl                                                                        

yetyzoowh jkzuvm yat                                                                        

ccc gpajft wmx wii ako fn dq i re u                                                                        

<a href=pregnancysymptomssigns.net Symptoms</a>                                                                          

cd lx gcfd mh rg pvbremhbfhxy i f drmcqtbimbuvod prbpfe inci gi uu                                                                        

ob rg sz vkhbxuezywlieluyxlprdgirbwgpmzmrdvitcp

# August 16, 2011 5:47 AM

geldlenen- said:

Geld Lenen wtvejaivj kpvdgdsl v xsewsuqku phhuksbiy oxsp wsk cq                                                                        

kjpwnhphe qylgnu bei vqxjxuywr zyehfe iaf                                                                        

ivxzihzul amftvn hwc                                                                        

mlb rqgtlv psi jui gpb df hl y gk m                                                                        

<a href=lenenzondertoetsingbkr.net Lenen</a>                                                                            

ef bv rifi ao to qgspdmhmhlbk j a vjypzjqgajubep xurewb wvho kg kz                                                                        

ir ud yj owbanqhrdwbomjrlcsnaltpiyjpyyybgrqadec

# August 23, 2011 5:40 AM

chanel said:

I recently came accross your blog and have been reading along. I thought I would leave my first comment. I dont know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.

Das ist sehr hilfreich für mich, Ich mag dieses Blog, ich kann eine Menge lernen.<a href="http://www.cooltasche.com">Chanel taschen</a> ist eine gute Website, es gibt Dinge, die Sie benötigen.

# September 16, 2011 10:01 PM

Gucci Tote Schultertasche said:

Thanks for sharing your article; it’s very nice, thanks. I hope can read more good articles

# September 29, 2011 11:09 PM

Ludda said:

When blogging about something like this you should provide code or at least working code after following the blog ...  This is kind of hard to try following.

# October 7, 2011 4:41 AM

Feextmof said:

to buy <a href=cheap-prada.weebly.com/>cheap prada</a>   and check coupon code available

# January 31, 2012 3:08 PM

icorsandre said:

buy a <a href=convert-dvd-to-ps3.weebly.com/>convert dvd to ps3</a>  , for special offer   , just clicks away

# February 6, 2012 1:46 PM

Soap behavior | Kemchotv said:

Pingback from  Soap behavior | Kemchotv

# February 16, 2012 10:40 PM

chanel Geldboerse said:

Ich mag sehr viel Ihre Art der Präsentation. Wir freuen uns auf mehr lesen von dir.

# March 6, 2012 2:18 AM

Tips for programmer said:

Pingback from  Tips for programmer

# March 8, 2012 11:32 AM

buy google +1 said:

kmaV1W Thanks a lot for the article. Fantastic.

# March 23, 2012 2:37 PM

Setting MessageHeaders.To field gets overwritten | PHP Developer Resource said:

Pingback from  Setting MessageHeaders.To field gets overwritten | PHP Developer Resource

# May 23, 2012 11:32 PM

DrulkDalaWritk said:

# May 26, 2012 6:02 AM

icons collection said:

<a href="www.standard-icons.com/.../portfolio.htm"> And variants are possible still?</a>

# October 7, 2012 1:36 PM

icons collection said:

<a href="yippyzone.com/index.php In my opinion you are not right. I am assured. I can defend the position. Write to me in PM.</a>

# October 10, 2012 3:48 AM

Eugene Nelubov said:

@dror was right code does not working fo me too.

made it working by removing behavior name from server side.

Server side web.config:

<system.serviceModel>

 <extensions>

   <behaviorExtensions>

     <add name="customBehavior" type="DevLeap.WCF.Behaviors.Extensions.CustomBehaviorExtensionElement, DevLeap.WCF.Behaviors.Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

   </behaviorExtensions>

 </extensions>

<services>

 <service name="DevLeap.WCF.Behaviors.Services.ServiceOne" >

   <endpoint

    address="net.tcp://localhost:35001/ServiceOne/"

    binding="netTcpBinding"

    contract="DevLeap.WCF.Behaviors.Contracts.IServiceOne" />

 </service>

</services>

<behaviors>

 <endpointBehaviors>

   <behavior>

     <customBehavior />

   </behavior>

 </endpointBehaviors>

 </behaviors>

</system.serviceModel>

# October 10, 2012 6:52 AM

Siseerex said:

click to view <a href="www.alldallascowboysjerseys.com/">dallas cowboys jerseys</a>  for gift  

# November 7, 2012 8:38 PM

Mitolors said:

must look at this <a href="www.chanel-outlet-bags.net/">chanel bags 2011</a>  for more  

# November 22, 2012 8:31 PM

Siseerex said:

to buy <a href="www.cheapcoach-handbags.net/">coach handbag</a>   to take huge discount  

# November 23, 2012 1:20 PM

Mitolors said:

cheap <a href="www.cocochanel-purses.com/">chanel purses</a>  for less  

# November 24, 2012 7:09 AM

SyncCemy said:

for <a href="www.alldallascowboysjerseys.com/">cheap dallas cowboy jerseys</a>  for more  

# December 3, 2012 5:49 PM

SyncCemy said:

cheap <a href="www.alldallascowboysjerseys.com/">dallas cowboy jerseys cheap</a>  for more detail  

# December 4, 2012 3:36 AM

Siseerex said:

buy a <a href="www.redwinelady.net/">hermes kelly</a>   to get new coupon  

# December 5, 2012 12:51 AM

shaqkuqh@gmail.com said:

Amazing! This blog looks just like my old one! It's on a completely different subject but it has pretty much the same layout and design. Superb choice of colors!

# December 9, 2012 10:01 PM

Lowtwera said:

best for you <a href="http://e--store.com/ ">coach outlet sale</a>  online   AASpHFDa  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 15, 2012 2:59 PM

binsseve said:

I am sure you will love <a href="http://e--store.com/ ">coach handbags outlet</a>  with confident   hXJEVYzb  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 16, 2012 10:13 AM

cyncNask said:

buy best <a href="http://e--store.com/ ">louis vuitton online</a>  with confident   nZOGLnID  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 18, 2012 12:30 PM

Kesquire said:

click <a href="http://e--store.com/ ">coach purse outlet</a>  with confident   Npqmpgvz  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 18, 2012 7:15 PM

Anedenaw said:

I am sure you will love <a href="http://e--store.com/ ">prada outlet</a>  suprisely   xhcWLPvA  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 18, 2012 7:40 PM

Feenepes said:

you must read <a href="http://e--store.com/ ">gucci online shop</a>   and check coupon code available   XwHhgSHV  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 20, 2012 12:03 PM

binsseve said:

check <a href="http://e--store.com/ ">prada outlet</a>  , just clicks away   KqHTRXSu  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 21, 2012 7:02 AM

GotteGam said:

check this link, <a href="http://e--store.com/ ">coach outlet</a>  with low price   HRfbeOCE  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 24, 2012 7:10 PM

emitlews said:

sell <a href="http://e--store.com/ ">gucci online store</a>  online shopping   coJMZvTJ  <a href="http://e--store.com/ "> http://e--store.com/ </a>

# December 26, 2012 10:55 AM

fdzpyypg@gmail.com said:

Thanks  for some other informative web site. Where else may just I am getting that type of information written in such an ideal approach? I have a mission that I'm simply now working on, and I have been on the look out for such info.

[url=http://www.wow-gold-team.com/]wow gold[/url]

# January 12, 2013 3:44 AM

HiftFult said:

you will like <a href=" ">cheap chanel handbags</a>  bAPXZDRC  [URL= - cheap chanel bags[/URL -  for less   RTSAmSUn  <a href=" ">  </a>

# February 6, 2013 2:59 PM

Secresee said:

best for you <a href=" ">discount chanel</a>  aaqAPPaq  [URL= - discount chanel[/URL -  for gift   sjvelggg  <a href=" ">  </a>

# February 10, 2013 12:15 AM

paspkift said:

get <a href=" ">fake chanel</a>  KBOCdaat  [URL= - chanel bags outlet[/URL -   and get big save   qztkdKOo  <a href=" ">  </a>

# February 12, 2013 12:10 AM

pofjtvbrjoc@gmail.com said:

You could definitely see your enthusiasm in the paintings you write. The sector hopes for more passionate writers like you who aren't afraid to say how they believe. At all times go after your heart. archeage gold www.cheap-archeage-gold.com

# February 22, 2013 7:09 PM

gsiqftg@gmail.com said:

You may also be partial to a particular material or style. Louis Vuitton monogram canvas webstorebagsforyou.webstarts.com

# March 17, 2013 4:36 AM

Aguiar said:

When some one searches for his essential thing, so he/she needs to be available that in detail, thus that thing is maintained over here.

# March 26, 2013 10:52 PM

F said:

Wonderful article. Concise, complete. Perfect

# April 3, 2013 2:27 PM

Presley said:

you're really a good webmaster. The site loading velocity is incredible. It kind of feels that you are doing any distinctive trick. Furthermore, The contents are masterpiece. you have done a excellent job on this topic!

# April 7, 2013 6:46 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)