Usually, in BizTalk we never work directly with transport specific data like HTTP headers and file names etc. Instead we manipulate the message context to instruct an adapter to add the transport specific data. Most of the time this works great and the BizTalk adapter does a good job shielding us from the nitty gritty details of the transport and let us focus on the data.
Sometimes though this is not enough. An example of this is when you need to add message specific data to the HTTP header using the WCF-WebHttp adapter. For example, we need to calculate an MD5 hash and add it to the Content-MD5 HTTP property for every outgoing message. This hash should, naturally, be unique for every unique message we send.
For most BizTalk developers it comes natural to use a pipeline component to do these kind of things. So that’s where I started off.
As stated in this blog post there is a property called HttpHeaders where we can set the header to whatever we want and then the adapter uses this property to create the actual HTTP header.
So the first thing that comes to my mind is to build a pipeline component that calculates the MD5 hash, format the HTTP header appropriately and set the HttpHeaders context property.
A quick test using Fiddler to inspect the HTTP request shows that an MD5 hash is indeed calculated and added to the HTTP header.
However, if we run the same test again, using another test file, the MD5 header is still the same even though the message body isn’t.
I haven’t found much documentation on this but I guess it has something to do with how BizTalk instantiate the adapter. In the blog post linked above the author mentions this behavior briefly in the last paragraph. The author suggests that using a dynamic send port will solve this issue. I haven’t tried that myself but at least for my scenario a dynamic port would be overkill and just add a bunch of complexity to the solution.
I think that in the BizTalk world it is often forgotten that when using a WCF adapter we have the full WCF stack at our disposal and in contrast to most other adapters in BizTalk we can actually execute code in the adapter.
I am not going to get in to the details about WCF extensibility and message inspectors but more information is available on MSDN.
Basically there is an interface called IClientMessageInspector that has a method called BeforeSendRequest that allows us to execute code just before the message is sent to the server.
An implementation of that interface that calculates the MD5 and add it to the HTTP header could look like this:
Once this is registered in a WCF behavior and added to the Machine.config (more on that in the MSDN link above) our behavior is available for selection in the Behavior tab on the WCF-WebHttp adapter properties for our send port.
Now running the same two tests again proves that we get different MD5 hashes for both messages.
Only, if ever, set the HTTP header in the BizTalk context if the data is static or only varies per port and not per message.
WCF extensibility gives us the opportunity to execute code just before data is sent, the pipeline doesn’t.