BizTalk Send Ports, WS-Addressing, ClientVia and non-http prefixed To headers, Part 2
In a previous post I explained how we had a need to use the WS-Addressing To header to send a non-http prefixed URI, such as urn:company/path/subpath/Service1, and how that was supported, after a fashion, out of the box in BizTalk Server. It did however come with the limitation of not being able to edit the WCF config in the BizTalk Server Administration Console GUI once you loaded it from a binding file. I don’t like limitations.
In this post I’ll show you how you can create a very simple WCF behavior to help you to set a RemoteAddress EndpointAddress Uri to be able to accomplish the same thing, while still being able to continue to edit the port configuration.
WCF behaviors allows you to intercept and inspect or alter messages or metadata, or in other ways modify the runtime behavior or processing of the same as they are sent or received. In this case we are creating a client behavior.
The behavior is in essence very very simple, it’s only purpose is to alter the endpoint address at runtime. The place where I choose to implement this is in the ApplyClientBehavior method of the IEndpointBehavior interface.
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
serviceEndpoint.Address = new System.ServiceModel.EndpointAddress(this.Uri);
Incidently, I borrowed this implementation with pride from the ClientVia behavior that comes with the .NET Framework. Apart from the fact that that behaviors sets the ClientRuntime.Via property and this sets the ServiceEndpoint.Address property the implementation is very close to exactly the same.
This allows you to configure BizTalk in the following manner.
The “Address (URI)” property can be set to anything (as long as it is http or https prefixed), since it will later be overridden.
In the behaviors section we now have two behaviors, clientVia:
and the new one I created, which I called remoteAddress:
clientVia is configured as the actual URI of the service we need to call, while the remoteAddress behaviors is configured with the value we want to have in the To header.
The solution contain three files of interest.
The App.config file holds a snippet of configuration that needs to be placed in machine.config or in the BizTalk WCF-Custom WCF extension part of the Send Handler of the host that handles the WCF calls being made. It exists to make the behavior available to the BizTalk process and looks like this:
<add name="remoteAddress" type="bLogical.BizTalk.WSAHelper.RemoteAddressElement, bLogical.BizTalk.WSAHelper, Version=188.8.131.52, Culture=neutral, PublicKeyToken=3672865486d21857"/>
It points to the RemoteAddressElement class, whose responsibility it is to point out the type of the behavior and create new instances.
The RemoteAddressBehavior then in turn does the already above explained logic.
The project and code is available here.
I suppose a custom pipeline component setting the Address, or a Dynamic Send port for easier cases of configuration might also do the trick.