WS-addressing and MessageId

Topics: Technical Questions
May 13, 2009 at 4:08 PM

Hi, just a few  quick questions:

If I use WS-addressing in my virtual service and in the service that I have virtualised, is the MessageId header preserved by the broker?

If not ,(and I suspect not),  is it possible to have client side behaviors implemented as policies on the dispatcher to grab the outgoing MessageId, and then store it along with the incoming MessageId? I want to be able to link the client call to what happens in the service by means of the MessageId.

Developer
May 20, 2009 at 3:29 PM
Edited May 20, 2009 at 3:29 PM

The MSE does not flow the MessageID header in WS-Addressing.  You would need to flow this manually by adding client side behaviors to the outgoing channel the MSE creates.  There is a catch, so this is a great question to have posted.

You can create an implementation of WCF's IClientMessageInspector and put it in a policy assertion with either an OpVer, Resource, or SystemInstance subject selected.  Then create the appropriate Policy with a matching subject and apply it to that entity.

So if you create an OperationVersion assertion type, you'd need to create a Policy for an OperationVersion and then apply the policy to the OperationVersion you want to affect.

There are two catches.

1) if you implement IClientMessageInspector.BeforeSendRequest() like the following: 

               string messageId = OperationContext.Current.IncomingMessageHeaders.MessageId.ToString();

               request.Headers.MessageId = new System.Xml.UniqueId(messageId); 

 This would be good for a runtime that acted as both a messenger and broker.  For distributed messenger & broker, you would need to extract the messageId at the MSE messenger's endpoint (IDispatchMessageInspector).  Add it as a custom header so it flows through the broker, and then in your IClientMessageInspector, retreive your custom header and set the MessageId on the request parameter (and probably remove your custom header so it doesn't propogate to the service implementation).  This is needed because of the extra hop between the Messenger and Broker.

 

2) The request object you are modifying in #1 is still the internal cannonical message version used by the MSE (Soap12, Addressing 10).  The last step in the MSE pipeline is to repackage the outgoing request to match the MessageVersion that the service implementation expects. (i.e. SOAP12, SOAP11, POX, etc.).  We do this with an IClientMessageInspector that always executes last (after any policy).  The problem is that it doesn't propogate WS-Addressing headers.  The good news is you just need to make sure your policy assertion runs after the MSE's.  You do this by explicitly adding the MSE's assertion to your policy and ordering them properly.

a) Launch the WCF Policy Assertion Type import wizard (Tools, Load Policy Components, WCF Behavior Assertion Type)

b) use the following XAML for the assertion you want to load:

<beh:ChannelEndpointBehaviorExtension xmlns:beh="clr-namespace:Microsoft.MSE.Runtime.Services.Behaviors;assembly=Microsoft.MSE.Runtime.Services">
</beh:ChannelEndpointBehaviorExtension>

c) give the Assertion Type and Assertion a name (i.e. MSE_ChannelEndpointBehavior)

d) Assign an assertion type subject (OpVer, Resource, SystemInstance).  Complete the wizard.

e) Using an OpVer policy as an example of where you've applied your IClientMessageInspector implementation, Add this new assertion to your policy you already have on the OpVer

f) Make sure you re-order the assertions in your policy such that the MSE_ChannelEndpointBehavior is listed ABOVE your message inspector assertion.

Again, what we are doing here is just making sure that the default MSE behavior to transform the message to the proper outbound message version is applied before your assertion runs.  This allows you to set the WS-Addressing headers to the actual outbound request.