How to use an Adapter built using WCF LOB Adapter SDK within a WCF Custom Binding?

Windows Communication Foundation (WCF) ships with a set of pre-defined bindings out of the box in order to satisfy most common scenarios. WCF also provides an ability to create user-defined custom bindings not provided by the system. This can be done in one of the following ways:

1) Create a new binding that derives from a built-in binding such as System.ServiceModel.BasicHttpBinding

2) Create a new binding that derives from System.ServiceModel.Channels.Binding

3) Create a Custom Binding (i.e. use System.ServiceModel.Channels.CustomBinding) and add binding elements to it

See "WCF Bindings in Depth" for more information.

WCF LOB Adapter SDK provides an AdapterBinding class that derives from System.ServiceModel.Binding containing a default profile to surface Adapter as a Standard Adapter Binding (Point #2).

The main objective of this document is to demonstrate how an adapter built using WCF LOB Adapter SDK can also be used within a user-defined Custom Binding (Point #3). Custom Binding is a container in which the user can fill-in various binding elements. These binding elements create the channels and listeners necessary to build incoming/outgoing channel stacks at runtime. Each binding element in the binding represents a processing step when sending or receiving messages. The order of the binding elements is important when creating a binding. A custom binding can be created either programmatically or in an application configuration file.

Contents

· Surfacing Standard Adapter Binding

· Surfacing Adapter as a Binding Element for use in Custom Binding

· Creating Custom Binding configuration using Microsoft Service Configuration Editor

· Using Adapter within a WCF Custom Binding in BizTalk WCF Adapter

· Creating “Custom Binding” programmatically in .NET

· Conclusion

Exposing Standard Adapter Binding

 

Today, the WCF LOB Adapter is surfaced as a binding and cannot be used within another Custom Binding. Before we talk about how to accomplish that, let’s see how the adapter is surfaced as a standard adapter binding.

The classes MyAdapterBindingCollectionElement, MyAdapterBindingElement and MyAdapterBinding are generated by Adapter Development Code Generation Wizard to provide a standard binding (“sample adapter profile”) to the adapter consumer. The class AdapterBindingCollectionElement is a WCF StandardBindingCollectionElement that links AdapterBinding with the WCF configuration system. The bulk of the implementation is delegated to AdapterBindingElement which derives from WCF System.ServiceModel.Channels.StandardBindingElement.

The AdapterBindingElement has properties that correspond to the properties on AdapterBinding. There are functions in AdapterBindingElement class that map the properties from and to Adapter Binding.

The standard binding AdapterBinding is registered in the WCF configuration as follows.

<configuration>

  <system.serviceModel>

    <extensions>

      <bindingExtensions>

        <add name="helloWorldBinding" type="Microsoft.WCF.Samples.Adapters.HelloWorldAdapterBindingCollectionElement, HelloWorldAdapter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc15bf5d5e9bce82" />

      </bindingExtensions>

    </extensions>

  </system.serviceModel>

</configuration>

Once the binding is known to the WCF configuration system, it can be referenced from the serviceModel configuration section by the client endpoint.

<configuration>

  <!-- WCF Endpoint Information -->

  <system.serviceModel>

    <client>

      <!-- Define helloWorldBinding endpoint -->

      <endpoint

        address="hello://"

        binding="helloWorldBinding"

        bindingConfiguration="HelloWorldAdapterBinding"

        contract="helloMicrosoftWCFSamplesAdapters"

        name="myHelloConfig">

      </endpoint>

    </client>

    <bindings>

      <!-- Define binding element properties -->

      <helloWorldBinding>

        <binding name="HelloWorldAdapterBinding" Count="2"/>

      </helloWorldBinding>

    </bindings>

  </system.serviceModel>

</configuration>

Well, so far we have only talked about how the default adapter binding is exposed to the configuration. Let’s get to the point now and show how it can be exposed as a binding element.

Surfacing Adapter as a Binding Element for use in a Custom Binding

In order to expose the Adapter as a binding element to the WCF configuration system, we need to create a new class that extends from BindingElementExtensionElement class. (Note Adapter Development Code Generation Wizard generates this class).

See attached a sample BindingElementExtensionElement derived class.

The base Adapter class in WCF LOB Adapter SDK derives from System.ServiceModel.Channels.TransportBindingElement. The sub-class of BindingElementExtensionElement creates the custom adapter in overridden CreateBindingElement() method. If adapter wants the end-user to supply custom properties on this binding element, these properties should be explicitly defined within this class. The InitializeFrom() and ApplyConfiguration() functions should map the properties from and to the adapter. If there are properties defined in AdapterBinding (AssuresOrderedDelivery, QueuedDelivery, Scheme, etc.) or Binding (Name, Namespace, CloseTimeout, SendTimeout, etc.) that need to be exposed in this binding element, each property needs to be defined within this new class.

Once this new class is added, recompile the DLL and add to GAC. The next step is to register this with configuration, so that CustomBinding implementations can reference our adapter as a binding element.

<configuration>

  <system.serviceModel>

    <extensions>

      <bindingElementExtensions>

        <add name="helloWorldAdapter" type="Microsoft.WCF.Samples.Adapters.HelloWorldAdapterBindingElementExtension, HelloWorldAdapter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc15bf5d5e9bce82" />

      </bindingElementExtensions>

    </extensions>

  </system.serviceModel>

</configuration>

The extension can be referenced from custom bindings to use adapter with other binding elements, as shown below.

<configuration>

  <system.serviceModel>

    <client>

      <!-- Define a client endpoint that uses a Custom Binding for HelloWorldAdapter -->

      <endpoint

        address="hello://"

        binding="customBinding"

        bindingConfiguration="HelloWorldAdapterBinding"

        contract="helloMicrosoftWCFSamplesAdapters"

        name="myHelloConfig">

      </endpoint>

    </client>

    <bindings>

      <!-- Define the custom binding for HelloWorldAdapter -->

      <customBinding>

        <binding name="HelloWorldAdapterBinding">

          <textMessageEncoding/>

          <privacyNoticeAt url="https://microsoft.com" version="2"></privacyNoticeAt>

          <helloWorldAdapter count="10"/>

        </binding>

      </customBinding>

    </bindings>

  </system.serviceModel>

</configuration>

Creating Custom Binding configuration using Microsoft Service Configuration Editor

 

The user can also use the Microsoft Service Configuration Editor tool provided with Windows SDK to generate a configuration file. Once the <bindingElementExtension> is specified in the configuration, the tool recognizes it and allows adding this as a binding element during Custom Binding creation.

Using Adapter within a WCF Custom Binding in BizTalk WCF Adapter

 

Also, once the adapter is registered as a binding element extension. It can be used by the BizTalk WCF Adapter to configure a Static or Dynamic Port using Transport Type “WCF-Custom” and Binding Type “customBinding”. In WCF-Custom Transport Properties dialog, select Binding Type “customBinding” and right-click on CustomBindingElement and select “Add extension”. Selecting “Add extension” will show Select Binding Element Extension dialog, from where the adapter binding element extension can be selected.

Creating “Custom Binding” programmatically in .NET

 

The following code-snippet shows how a Custom Binding can be created programmatically and used in the context of channel programming (dealing with WCF request and response messages).

            // Create custom binding

            CustomBinding customBinding = new CustomBinding();

            // Create privacy binding element

            PrivacyNoticeBindingElement privacyNoticeElement = new PrivacyNoticeBindingElement();

            // Create adapter binding element

            HelloWorldAdapter adapter = new HelloWorldAdapter();

            adapter.Count = 1;

            // Add binding elements to the custom binding

            customBinding.Elements.Add(privacyNoticeElement);

            customBinding.Elements.Add(adapter);

           

            // Enumerate through all the configured custom bindings

            EnumerateConfiguredCustomBindings();

            // Enumerate through all the available binding element extensions

            EnumerateAllAvailableBindingElementExtensions();

            // Create EndpointAddress

            EndpointAddress address = new EndpointAddress("hello://");

            // create channel factory using channel shape IRequestChannel

           IChannelFactory<IRequestChannel> requestChannelFactory = customBinding.BuildChannelFactory<IRequestChannel>();

            // open channel factory

            requestChannelFactory.Open();

  ...

 

Conclusion

 

The Adapter built using WCF LOB Adapter SDK can be exposed to WCF client as both Transport Channel (registered in WCF configuration using System.ServiceModel.Configuration.BindingElementExtensionElement) and a Binding (registed in WCF configuration using System.ServiceModel.Configuration.StandardBindingElement).

The following code-snipped shows a WCF client proxy that uses the endpoint defined in app.config to communicate to a WCF service. The endpoint can use either the Standard Adapter Binding or the Custom Binding that includes one or more binding element extensions.

            helloMicrosoftWCFSamplesAdaptersClient proxy = new helloMicrosoftWCFSamplesAdaptersClient("myHelloConfig");

            Console.WriteLine(proxy.SayHelloWorld("Sonu"));

Here are two configurations side by side:

WCF Service Model using Standard Adapter Binding

WCF Service Model using Custom Binding

    <system.serviceModel>

        <client>

            <endpoint

              address="hello:/"

              binding="helloWorldBinding"

              bindingConfiguration="HelloWorldAdapterBinding"

              contract="helloMicrosoftWCFSamplesAdapters"

              name="myHelloConfig" />

        </client>

        <bindings>

            <helloWorldBinding>

                <binding

                    name="HelloWorldAdapterBinding"

                    closeTimeout="00:01:00"

                    openTimeout="00:01:00"

                    receiveTimeout="00:10:00"

                    sendTimeout="00:01:00"

                    Count="4" />

            </helloWorldBinding>

        </bindings>

    </system.serviceModel>

  <system.serviceModel>

    <client>

      <!-- Define client endpoint -->

      <endpoint

        address="hello://"

        binding="customBinding"

        bindingConfiguration="CustomHelloWorldBinding"

        contract="helloMicrosoftWCFSamplesAdapters"

        name="myHelloConfig" />

    </client>

    <bindings>

      <!-- Create custom binding -->

      <customBinding>

        <binding name="CustomHelloWorldBinding">

          <textMessageEncoding />

          <privacyNoticeAt url="https://microsoft.com" version="2" />

          <helloWorldAdapter count="4" />

        </binding>

      </customBinding>

    </bindings>

  </system.serviceModel>

  <system.serviceModel>

    <extensions>

      <bindingExtensions>

        <add name="helloWorldBinding" type="Microsoft.WCF.Samples.Adapters.HelloWorldAdapterBindingCollectionElement, HelloWorldAdapter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc15bf5d5e9bce82" />

      </bindingExtensions>

    </extensions>

  </system.serviceModel>

  <system.serviceModel>

    <extensions>

      <bindingElementExtensions>

        <add name="helloWorldAdapter" type="Microsoft.WCF.Samples.Adapters.HelloWorldAdapterBindingElementExtension, HelloWorldAdapter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc15bf5d5e9bce82" />

      </bindingElementExtensions>

    </extensions>

  </system.serviceModel>

 

References

· Creating User-Defined Bindings

· Transport Extensibility Sample – UDP

 

SampleAdapterBindingElementExtensionElement.cs