Saturday, April 12, 2008

Fixing BizTalk's WCF Message Contract Mix-Up, Part 2

I know of three ways to fix the Message Contract Mix-Up discussed in the last post. The first two require changing the signatures of your operation contracts to replace the WCF-generated message contracts with message contracts you define yourself. (Perhaps you've read books or heard WCF experts who say you needn't bother defining message contracts except in the unusual case. Then I guess BizTalk is an unusual case, as you might have suspected.)

1. Change the operation contract’s parameter and return value to message contracts with IsWrapped = false, like this:

[ServiceContract(Namespace = "urn://MyCompany.Purchasing.1_0_0.com")]
public interface IPurchasing
{
[OperationContract]
OrderStatusMessage PlaceOrder(PurchaseOrderMessage message);
}

[MessageContract(IsWrapped=false)]
public class PurchaseOrderMessage
{
[MessageBodyMember(Namespace = "urn://MyCompany.Purchasing.1_0_0.com")]
public PurchaseOrder PurchaseOrder;
}

[MessageContract(IsWrapped=false)]
public class OrderStatusMessage
{
[MessageBodyMember(Namespace = "urn://MyCompany.Purchasing.1_0_0.com")]
public OrderStatus OrderStatus;
}

If you declare your own message contracts but set IsWrapped to false (the default is true), then WCF will not generate any message contract element in the SOAP message at all. Instead, WCF will place the field with the MessageBodyMember attribute – which happens to be your data contract, PurchaseOrder – directly at the root of the SOAP body. Thus the SOAP message received by BizTalk will have an element named PurchaseOrder at its message type. Bingo! The great thing about this solution is you don’t need to do anything special on the BizTalk side to make your WCF adapters behave as you originally expected.

2. Same as 1. above, except the message contracts have IsWrapped = true. This will make the message contracts visible in your SOAP bodies, but you'll control their content instead of WCF. Generate XSD schemas for the message contracts and put them in your BizTalk project. Write message maps to transform message contract schemas to and from data contract schemas. Use the message maps to transform message contracts into data contracts in your inbound ports and to transform data contracts into message contracts in your outbound ports.

This solution will increase the number of schemas and message maps you’ll maintain. But unlike the previous solution, this one makes the message structures consistent, whether you look at them from the perspective of the WCF contracts, the BizTalk schemas, or the actual SOAP messages on the wire.

3. If you can’t, or aren’t willing, to define your own message contracts, but you’re able to add some WCF attributes, you can work out a compromise that allows BizTalk to navigate through the WCF-generated message contracts without knowing all about their schemas. The final post in this series will explain how to do that.

1 comment:

BiztalkNewbie said...

Hi,

I am trying to consume a WCF service ,which accepts message contract as its input, in my biztalk orchestration. The message contract has both the message header and message body part. But the multipart message for the input generated in the orchestration has only the body part. Could you please tell me a way out so that i can send the message header too along with the body?