Service Bus for Windows Server – Posting messages for BizTalk

In my previous post I talked about how we are using Service Bus as our queueing mechanic, from which we read messages using BizTalk. When using Paulo Salvatori’s test client we could read these messages in BizTalk, however when we were publishing messages from our own .NET applications, we weren’t able to receive them in BizTalk. These were the errors we got in the event log:

The adapter “WCF-Custom” raised an error message. Details “System.ServiceModel.CommunicationException: Unrecognized message version.

The adapter “WCF-Custom” raised an error message. Details “System.FormatException: Input string was not in a correct format.

Error
After some research, I found out this is due to the way the messages are being deserialized by the BizTalk WCF adapter. To solve this, when placing the messages on Service Bus, we have to publish them as WCF messages, instead of using the Service Bus SDK.

Since we have a lot of different messages which are being sent, making datacontracts and message contracts for each of them was not an option. Therefor, we created a generic message contract, which will work as an envelope for the messages. Start by creating a DataContract like this:

1
2
3
4
5
6
7
8
9
10
11
12
[DataContract]
public class Notification
{
string xml;
 
[DataMember]
public string Xml
{
get { return xml; }
set { xml = value; }
}
}

Next create the MessageContract for the message which will hold the data:

1
2
3
4
5
6
7
8
9
10
11
[MessageContract(IsWrapped = false)]
public class NotificationMessage
{
public NotificationMessage(Notification notificationMessage)
{
NotificationMessageData = notificationMessage;
}
 
[MessageBodyMember]
public Notification NotificationMessageData { get; set; }
}

And finally, create the ServiceContract:

1
2
3
4
5
6
7
[ServiceContract]
public interface INotificationsService
{
[OperationContract(Action = "SendRequest", IsOneWay = true)]
[ReceiveContextEnabled(ManualControl = true)]
void SendRequest(NotificationMessage notificationMessage);
}

Before we can use the service, you need to add the endpoint configuration to your config file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="sb://localhost/ServiceBusDefaultNamespace/biztalktopic"
                behaviorConfiguration="securityBehavior"
                binding="netMessagingBinding"
                bindingConfiguration="netMessagingBinding"
                contract="NotificationServiceLibrary.INotificationsService"
                name="requestTopicClientEndpoint"/>
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="securityBehavior">
          <transportClientEndpointBehavior>
            <tokenProvider>
              <windowsAuthentication>
                <stsUris>
                  <stsUri value="https://localhost:9355/" />
                </stsUris>
              </windowsAuthentication>
            </tokenProvider>
          </transportClientEndpointBehavior>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <netMessagingBinding>
        <binding name="netMessagingBinding"
                 sendTimeout="00:03:00"
                 receiveTimeout="00:03:00"
                 openTimeout="00:03:00"
                 closeTimeout="00:03:00"
                 sessionIdleTimeout="00:01:00"
                 prefetchCount="-1">
          <transportSettings batchFlushInterval="00:00:01"/>
        </binding>
      </netMessagingBinding>
    </bindings>
    <extensions>
      <behaviorExtensions>
        <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </behaviorExtensions>
      <bindingExtensions>
        <add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </bindingExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

Now to actually send out the messages, we need to create a message in our .NET code. Here originalXML is the full XML from the original message.

1
2
3
// Create request message
var notification = new Notification{Xml = originalXML};
var notificationMessage = new NotificationMessage(notification);

Now create the channel using the binding we previously defined.

1
2
3
// Create a channel
var channelFactory = new ChannelFactory&lt;INotificationsService&gt;("requestTopicClientEndpoint");
var channel = channelFactory.CreateChannel();

And finally we can send the message.

1
2
// Send the message
channel.SendRequest(notificationMessage);

Now to receive the messages in BizTalk, we have to make a small change to the receive location listening on the queue / topic. Open the configuration of the WCF-Custom adapter on the receive location, go to the tab Messages, and set Inbound BizTalk message body to Path, set Body path expression to

/*[local-name()='NotificationMessageData']/*[local-name()='Xml']

and set Node encoding to String.

MessagesSettings
Now when we receive the message from Service Bus, BizTalk will extract the original message, and will publish this message to the MessageBox, where it will continue it’s normal path. You can download the solution I used for testing from here.

Leave a Reply

Your email address will not be published. Required fields are marked *