Hosting BizTalk WCF Send Adapters in your Custom Application

The BizTalk Adapters for WCF is a collection of several adapters that are designed to make it easy to create BizTalk applications that communicate with WCF-based services or line-of-business applications.

It ships with five physical adapters, corresponding to predefined WCF bindings (such as, BasicHttp, WsHttp, NetTcp, NetNamedPipe and NetMsmq). For more flexibility, it also ships with a custom adapter that can be configured with more control over WCF binding and behavior informations.

Also included with a BizTalk Server license, the Line of Business Adapter Pack includes several adapters for communication with line-of-business applications or databases from common vendors.

Additionnaly, thanks to the WCF LOB Adapter SDK, one can build his custom connectors for enabling access to in-house or proprietary data sources in a streamlined way. Many commercial vendors offer additional adapters built this way to enable BizTalk Applications to communicate with and expanded choice of line-of-business systems.

As a matter of fact, adapters built with the WCF LOB Adapter SDK are exposed as plain WCF transport-level bindings and thus can be reused in your custom .net applications, or any application that can consume a WCF binding.

In this post, I will show you how simple it is to re-use adapters that ship with BizTalk, or custom adapters built with the WCF LOB Adapter SDK, and host them in your custom applications.

Hosting Send Side WCF Adapters in your Custom Application

Using a WCF binding from a C# application is quite straightforward. After all, using WCF is as simple as ABC, right ?

1. A stands from Address.

The address represents the location of the WCF endpoint. It is commonly represented as a Uniform Resource Locator (URL).

var address = new EndpointAddress("mssql://localhost//SampleDb?");

2. B stands from Binding.

The binding is a collection of binding elements that gives the WCF runtime informations about the communication “stack” through which any given message passes through. A typical WCF communication stack can contain many channels, each of which is responsible for transforming and adapting the message so that it can be eventually transmitted to the target system. For this reason, the last channel in the stack is a transport-level channel.

Adapters build with the WCF LOB Adapter SDK are themselves transport-level WCF binding elements and therefore can be used directly in a communication stack. Those adapters, like any other bindings, are registered in the machine.config. For instance, here is the relevant snippet, corresponding to the WCF-SQL adapter:

      <bindingElementExtensions>
        <!- ... -->
        <add name="sqlAdapter" type="Microsoft.Adapters.Sql.SqlAdapterBindingElementExtensionElement, Microsoft.Adapters.Sql, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </bindingElementExtensions>

So, instantiating any given binding can be done very easily:

// create binding element

var adapter = new Microsoft.Adapters.Sql.SqlAdapterBindingElementExtensionElement();
adapter.AllowIdentityInsert = false;
adapter.EnableBizTalkCompatibilityMode = false;

var bindingElement = (BindingElement) Activator.CreateInstance(adapter.BindingElementType);
...

// create custom binding

var binding = new CustomBinding();
binding.Elements.Add(bindingElement); // add transport-level binding element last

// configure binding

binding.OpenTimeout = TimeSpan.FromSeconds(30);
...

Adapters built using the WCF LOB Adapter SDK all have a binding class, such as SqlAdapterBinding for instance. This class be instantiated and configured directly, instead of using a CustomBinding class like I have shown in my example above. However, I’m not sure how to get to this class directly from the information stored in machine.config.

3. C stands for Contract.

The contract represents the set of methods, with their arguments and return types, that the line-of-business system exposes. In most C# application, the service contract is exposed as a C# interface. Since we are dealing with adapters, however, there is no specific interface that can be used.

Instead, we need to rely on the channel shape, that corresponds to the most common communication exchange pattern used to access various systems, applications or databases.

Most adapters that ship with BizTalk support two-way communication. Therefore, the most sensible contract would be IRequestChannel. This contract allows an application to send and abitrary request, represented by a WCF Message object, and receive a response in return.

A Message is constructed with an Action, that makes sense to the adapter and a payload, supplied in the form of a class derived from BodyWriter.

private static Message InvokeAdapterRequest(Binding sqlBinding, EndpointAddress sqlAddress, String action, BodyWriter bodyWriter)
{
    using (var message = Message.CreateMessage(MessageVersion.Default, action, bodyWriter))
        return InvokeAdapterRequest(sqlBinding, sqlAddress, message);
}

private static Message InvokeAdapterRequest(Binding sqlBinding, EndpointAddress sqlAddress, Message message)
{
    var channel = ChannelFactory<IRequestChannel>.CreateChannel(sqlBinding, sqlAddress);
    try
    {
        if (channel.State != CommunicationState.Opened)
            channel.Open();
        return channel.Request(message);
    }
    catch
    {
        channel.Abort();
    }
    finally
    {
        channel.Close();
    }
}

Here is, for instance, a simple way to call a stored procedure on SQL Server using the WCF-SQL Adapter:

public class XmlBodyWriter : BodyWriter
{
    private readonly string body_;

    public XmlBodyWriter(string body)
        : base(true)
    {
        body_ = body;
    }

    protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
    {
        writer.WriteRaw(body_);
        writer.Flush();
    }
}


private static void Main(string[] args)
{
    var address = new EndpointAddress("mssql://localhost//SampleDb?");

    // create binding element

    var adapter = new Microsoft.Adapters.Sql.SqlAdapterBindingElementExtensionElement();
    adapter.AllowIdentityInsert = false;
    adapter.EnableBizTalkCompatibilityMode = false;

    var bindingElement = (BindingElement) Activator.CreateInstance(adapter.BindingElementType);

    // create custom binding

    var binding = new CustomBinding();
    binding.Elements.Add(bindingElement); // add transport-level binding element last

    // configure binding

    binding.OpenTimeout = TimeSpan.FromSeconds(30);

    const string action = "TypedProcedure/dbo/usp_SelectRecords";
    var bodyWriter = new XmlBodyWriter("<ns0:usp_SelectRecords xmlns:ns0='http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo' />");

    using (var response = InvokeAdapterRequest(binding, address, action, bodyWriter))
    {
        // use response message
        Console.WriteLine(response.ReadOuterXml());
    }
}

Conclusion

This post shows a simple way to re-use any WCF LOB Adapter SDK-based adapters, in your own custom applications.

You probably will not have a use for this very often. Be we, at Moskitos, are building a new generation EAI/ESB Platform available as a Cloud-based application and our custom adapters are based on the WCF LOB Adapter SDK. Additionnaly, if our clients want to use BizTalk on-premise as well, we can take advantage of the BizTalk Adapter pack to allow our solution to communicate with other line-of-business systems.

This entry was posted in BizTalk, Wcf. Bookmark the permalink.

One Response to Hosting BizTalk WCF Send Adapters in your Custom Application

  1. Very nice article…
    Might me used for inline send in an orchestration??

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s