Welcome back to the “Throwing typed WCF faults back to consumers in a BizTalk messaging only application” blog series. This is the 5th part in the series and specifically focuses on copying custom headers from the request message to the response message to aid BizTalk (or other messaging engine) service consumers by ensuring the response message contains enough context that it can be handled independently from the original request, and it also deals with copying over the SOAP action from the request message to the fault message to ensure that .NET (and other programmatic frameworks) consumers can properly consume typed fault messages. If you haven’t yet read the prior entries in this series then follow the below links before you continue reading this entry.
The previous entry in this blog series highlighted how the correct SOAP action must be attached to the generated typed fault message before it is sent back to a .NET consumer or it will not be able to catch the typed fault and will instead only see a generic System.ServiceModel.FaultException exception which doesn’t contain all the exception detail of interest. In order to get around this issue we must ensure that we copy the SOAP action from the original request message to the response message and I have achieved this via an endpoint behavior. It should be noted that endpoint behaviors always execute after service behaviors, thus this endpoint behavior would override the hardcoded SOAP action that was set on the fault in the service behavior built in the fourth part of this blog series.
The first entry in this blog series also highlighted that if a BizTalk consumer of the service in question wanted to build a messaging only application, they would find that the fault message would not contain enough information in it for an operations staff to deal with it if it were routed to an exception handling mechanism, since it doesn’t contain any identifying elements, and thus an orchestration or some other mechanism would need to be created to inject values from the request message into the exception before it was passed to the exception handler. It would be ideal if the service catered for a mechanism to optionally copy over context from the request message to the response message and I decided that the context would be contained within a custom SOAP header which would also be copied over by an endpoint behavior.
I decided to kill two birds with one stone and solve both these problems with a single endpoint behavior which makes use of a custom message inspector which copies over headers from the request to the response. There is no reason why these couldn’t be split out into two separate behaviors altogether or at least two separate message inspectors.
This message inspector uses the WS-Addressing MessageID and RelatesTo headers to form a correlation token to link a request message to a response message, adding the MessageID to a dictionary (note that you should assess how best to clear out your caches to ensure you don’t encounter a memory leak) as a key with the values being made up of headers that I wanted to persist for the current message. The AfterReceiveRequest method of the message inspector which persists the headers to be copied over looks like the below. Note that if a MessageID is not provided by the client then one is made up and applied to the RelatesTo header to ensure that request and response correlation is possible in the message inspector.
The BeforeSendReply method which populates headers (including the SOAP action) on the reply message from the appropriate cached instance using the RelatesTo header on the reply message as a correlation token looks like the below.
In order to enlist this message inspector you must create an endpoint behavior as below.
And in order to bind the endpoint behavior you must create a behavior extension element class as below, which is very simple since our endpoint behavior doesn’t expose any parameters.
You will now need to build your endpoint behavior project, register it in the GAC, and register it in your machine.config files. As stated in part three of this blog series, my colleague Shadab has written a blog post on using WIX installers to install custom behaviors which includes registering them in the required machine.config so that is worth a read if you want more details on this.
You can now add this endpoint behavior to your BizTalk WCF-Custom or WCF-CustomIsolated receive location. On the behaviors section of the adapter configuration you should now be able to right click on EndpointBehavior, choose add extension and select the behavior name that you bound your extension element class to in the machine.config. If you don’t see it in the list then either your code has some problems in it, you haven’t registered the assembly in the GAC correctly, you haven’t registered the behavior in your machine.config files correctly, or you haven’t restarted the BizTalk Administration Console after doing the aforementioned tasks.
The result of this is .NET consumers of the service are now able to catch the typed faults and access contained elements as illustrated in the below screenshot. This is purely a result of the message inspector copying the SOAP Action from the request message to the response message.
To illustrate this a bit better, take a look at the below request message sent to the service from SOAPUI. Note the Identifier custom header included in the message.
The result of this is that it will be copied over to the response as well as below. Note that if the request did not contain the Identifier header then it would not be included in the response. If a MessageID was not sent with the request (this can be controlled via the WS-A tab in SOAPUI) then the RelatesTo header would not be included in the response.
I will discuss the usage of the custom headers by BizTalk a bit more in the next entry in this blog series in which I will describe how the client experience has been improved through the usage of the solutions described in this blog series.
If you are interested in reading further then do follow the links to further entries in this blog series.