This section covers a few other integration considerations that are important in using the rich feature set of the BizTalk WCF adapters. These considerations, such as custom behaviors and SOAP headers, extend the functionality of the adapters to facilitate powerful integration capabilities.
Enabling Custom Behaviors
Custom behaviors enable the customization of WCF receive locations and send ports to handle specific integration requirements such as security and auditing. Custom behaviors play a significant role in the integration of services through allowing the capabilities of the underlying communication channel to be enhanced. Typically, custom behaviors are specified in WCF Service Contracts in the following manner:
[OperationContract(Action = "*", IsOneWay = true)]
[CustomBehavior(CustomBehaviorApplies.InMessage)]
[TransactionFlow(TransactionFlowOption.Allowed)]
void Retrieve(Message inMessage);
In cases where advanced custom behavior extensions need to be enabled, the IEndpointBehavior interface needs to be implemented for the custom behavior class. The IEndpointBehavior adds the binding parameters that are required by the WCF runtime to apply the custom behavior. The following code fragment illustrates the implementation of a custom endpoint behavior:
Figure 23 – Implementing IEndpointBehavior
public class CustomEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters)
{
foreach (OperationDescription operation in
endpoint.Contract.Operations)
{
// Add your implementation.
}
}
public void ApplyClientBehavior(ServiceEndpoint endpoint,
ClientRuntime clientRuntime)
{
// Nothing to implement.
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
// Nothing to implement.
}
public void Validate(ServiceEndpoint endpoint)
{
// Nothing to implement.
}
}
As illustrated in the above code fragment, the parameters of the custom behavior need to be added to all the operations of your endpoint. This enables the WCF runtime to build the channel stack of the service with the custom behavior. For more information about implementing an IEndpointBehavior, see http://go.microsoft.com/fwlink/?LinkId=119800.
After the implementation of the IEndpointBehavior, for BizTalk Server to recognize the custom behavior as a configuration option, a BehaviorExtensionElement needs to be defined. Note that this is only required when a custom behavior extension element needs to be enabled.
The BehaviorExtensionElement can be implemented in the following manner:
Figure 24 – Implementing a Behavior Extension Element
public sealed class CustomBehaviorExtension :
BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(CustomEndpointBehavior);
}
}
protected override object CreateBehavior()
{
return new CustomEndpointBehavior
(this.CustomBehaviorAppliesTo);
}
[ConfigurationProperty("customBehaviorAppliesTo",
DefaultValue = CustomBehaviorApplies.Both)]
public CustomBehaviorApplies CustomBehaviorAppliesTo
{
get
{
return (CustomBehaviorApplies)
this["customBehaviorAppliesTo"];
}
Set
{
this["customBehaviorAppliesTo"] = value;
}
}
}
As illustrated by the above code fragment, a custom behavior extension needs to be defined. The BehaviorType property needs to be overridden to return the endpoint behavior that implements the IEndpointBehavior interface. Furthermore, the CreateBehavior method needs to be overridden to return the configuration property of the custom behavior. This will allow the custom endpoint behavior to be recognized by BizTalk Server as a configuration option.
Configuring a Custom Behavior
After the IEndpointBehavior and the BehaviorExtensionElement are implemented in the above manner, the custom behavior of the solution needs to be configured with a receive location or a send port.
Figure 25 – WCF Send Port Behaviors
As depicted on the above diagram, the behavior elements of the custom binding will not be configured by default. This can be configured according to the behavior requirements of the solution. The following steps explain the configuration of a custom behavior in a BizTalk send port or a receive location:
- Build the BehaviorExtensionElement class as an assembly and GAC it to machine where the send port is running (note that the IEndpointBehavior should already be in the GAC).
- Add the following configuration setting into the machine.config file of the host.
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="CustomBehaviorExtension"
type="Virtusa.App.Services.Channel.CustomBehaviorExtension,
Virtusa.App.Services.Channel, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=70cf70c48ef4b25e"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
Note |
|---|
|
The configuration information of the behaviorExtensions should match the assembly that is used for the custom behavior. The SvcConfigEditor.exe utility that comes with Windows SDK can be used for editing .config files.
|
- Restart the BizTalk Host and the BizTalk Server Administration console.
- To complete the creation of the custom behavior, add extension elements by clicking the Add extension menu option. The following diagram depicts a default list of extension elements that are available for addition through the Add extension menu option.
Figure 26 – Behavior Extensions
After a behavior is configured in the above manner, the WCF adapter uses the configured behavior to handle an incoming service call or to execute an outgoing service call. The channel stack that is initiated by the adapter will hold the code that needs to be executed for the configured behavior.
Propagating Namespaces
The current implementation of BizTalk Server 2006 R2 has an issue in propagating the namespaces that are required for external service calls that use a custom binding. Therefore, when an external WCF service is consumed by a send port, the relevant namespaces that are required for the service call are not transferred with the service call.
This is categorized as a known issue in the KB article
http://support.microsoft.com/default.aspx?scid=kb;EN-US;942612.
The above update resolves this issue. Therefore, in instances where a custom binding is used, it is important that this update is applied to the relevant BizTalk Hosts.
Note that this update also resolves a transaction time-out issue and a template / encoding issue. See the KB article for more information.
Synchronous vs. Asynchronous Methods on a Custom Binding
For a variety of reasons including performance, the BizTalk WCF adapters only support the invocation of asynchronous methods of a WCF channel stack. However, in cases where a synchronous custom binding needs to be integrated with the adapters, asynchronous methods can be implemented to call the relevant synchronous implementation:
protected override IAsyncResult OnBeginSend(Message message
TimeSpan timeout, AsyncCallback callback, object state)
{
// Call the sync version of OnBeginSend.
Send(message, timeout);
return new AsyncResult(callback, state);
}
As seen in the above example, asynchronous methods need to be overridden to call the synchronous implementation. Therefore, when the WCF runtime calls the asynchronous method, in turn the synchronous method is called by the channel. Note that the AsynResult class in the above example is a wrapper class that implements the IAsyncResult interface.
Through the above mechanism, a custom binding with synchronous methods can be successfully integrated with the asynchronous channel invocation model of the adapters.
Accessing SOAP Headers Through Pipeline Components
Accessing SOAP headers through pipeline components can be considered as a useful feature to facilitate WCF contracts that use the SOAP header to transfer message context information. BizTalk Server provides APIs to access SOAP header context properties through custom pipeline components. The context properties are accessed by using the context property name and its target namespace. The following examples illustrate the reading and writing of context properties through a custom pipeline component.
Reading from the SOAP header
public IBaseMessage Execute(IPipelineContext pContext,
IBaseMessage pInMsg)
{
object readValue = pInMsg.Context.Read ("InboundHeaders",
"http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties").ToString();
return pInMsg;
}
Writing to the SOAP header
public IBaseMessage Execute(IPipelineContext pContext,
IBaseMessage pInMsg)
{
string writingValue = "<?xml version=\"1.0\"?>
<OrigDest xmlns=\"http://SOAPHeaderSchemas.OrigDestSOAPHeader\">
<Origination>Home</Origination>
<Destination>Work</Destination>
</OrigDest>";
pInMsg.Context.Write("OrigDest",
"http://schemas.microsoft.com/BizTalk/2003/SOAPHeader",
writingValue);
return pInMsg;
}
As illustrated in the above examples, the SOAP header can be accessed to read and write message context properties.
Note that a complete set of BizTalk message context properties that are accessible through pipeline components are available at http://go.microsoft.com/fwlink/?LinkId=119803.