Chris Restall

I am attempting to consume a service from Biztalk 06 R2 using WCF without using an orchestration. Basically, I'd like to use a direct bound via filters send/receive port with a WCF-BasicHttp Transport to send a message (instance of a complex schema) to a WCF service and have the service respond back with an instance of the schema (content modified). The R2 site claims this is possible but I've only been able to find examples involving orchestrations.

Here's what I've tried.

1. Created a simple console application to host a service that takes an instance of my Biztalk PO schema and returns it (logic in the service will result in modification of the content).

I used xsd.exe to create classes from the PO schema in my biztalk project. This resulted in classes generated from the schema but it looks like it changed the names of sub elements when it created classes out of them.

My Biztalk Schema:

<companyNamePO>

<order>

Many other nodes...

</companyNamePO>

Classes genrated by XSD:

companyNamePO

companyNameOrder

This seems to have implications on the schema that comes accross when I attempt to consume the service.

2. Compiled and Started the service up.

3. Attempted to use the Consume WCF wizard via the MetaData endpoint option. This resulted in several files being created.

--2 binding xml files

--3 schemas

--An orchestration

Do I need this orchestration I've tried just importing the binding files but this doesn't work. I have to disable all security and i still get a faultMessage back:

<s:Fault xmlnsTongue Tied="http://www.w3.org/2003/05/soap-envelope">
<s:Code>
<s:Value>sTongue Tiedender</s:Value>
<sTongue Tiedubcode>
<s:Value xmlns:a="http://schemas.xmlsoap.org/ws/2005/02/sc">a:BadContextToken</s:Value>
</sTongue Tiedubcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The message could not be processed. This is most likely because the action '<BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Operation Name="ProcessPOSellRules" Action="http://Testing.Common.POSellWCFServiceTest/IProcessPOSell/ProcessPOSellRules" /> </BtsActionMapping>' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.</s:Text>
</s:Reason>
</s:Fault>

Not sure what this means.....

I am also confused about the imported schema from the External service. This seems redundant. I aready have that schema in my Biztalk project, the original one from which I used XSD to generate the classes for use in my service as the schema instance will be the parameter to that service. This XSD generation resulted in the classes with differing names (described above) in the service which results in a schema with multiple root nodes being pulled over to biztalk by the consume wizard.

Is there a simple example of not using an orchestartion to do this. What imported files really need to be kept around I am also worried that if the schema changes in biztalk then I have to regenerate the classes using XSD for the service, then re-run the wizerd, reimport etc etc. This seems like the potential for a maintenance headache and I'm really having a hard time in seeing the benefit.

Any insight would greatly be appreciated.



Re: BizTalk R2 General wcf send port consume

Karahan Celikel - MSFT

Hi Mitre,

This is a known issue.

When you use BtsActionMapping, WCF adapter tries to match the operation name with an action defined in the BtsActionMapping, and if it can't find the Operation context property in the BTS message, it sets the whole BtsActionMapping as the action on the outgoing WCF message. Since you don't use the orchestration, the Operation context property is not set.

The workaround is simple: set the action of the send port directly to http://Testing.Common.POSellWCFServiceTest/IProcessPOSell/ProcessPOSellRules

If you still want to use the action mapping feature, you can set the BTS.Operation context property in a custom pipeline component.

Hope this helps.

-Karahan





Re: BizTalk R2 General wcf send port consume

mitre

Thanks Karahan, I'll be sure to give this a try!





Re: BizTalk R2 General wcf send port consume

mitre

OK so I've given it another go:

- <s:Envelope xmlnsTongue Tied="http://schemas.xmlsoap.org/soap/envelope/">
- <s:Body>
- <s:Fault>
<faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode>
<faultstring xml:lang="en-US">The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>

when just using:

http://Testing.Common.POSellWCFServiceTest/IProcessPOSell/ProcessPOSellRules

in the action. I'll kep playing with it.





Re: BizTalk R2 General wcf send port consume

mitre

So I was able to get a bit furthur with this. My basicHttp wcf service has a method called "ProcessPOSellRules" which takes an instance of myCompanyPO as a parameter. The service does nothing more than manipulate that instance and return it. I used xsd to generate a class from the biztalk schema and am using that in the service.

I used the Add generated items tool to consume this service from biztalk and as there is no orchestration, I've followed the workaround above and set the action as specified

. It apears to work to some extent but I am unclear as to what I may be doing wrong based on this soap fault message:

<faultstring xml:lang="en-US">OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'ProcessPOSellRules' and namespace 'http://myCompany.com/Integration/Common/POSellProcess'. Found node type 'Element' with name 'myCompanyPO' and namespace 'http://myCompany.com/Integration/Common/POSellProcess'</faultstring>

I'm not sure why the Body of the instance message from Biztalk would require the method name of the service Doesn't the action I specify in the configuration inform the service as to what method to pass the schema instance to





Re: BizTalk R2 General wcf send port consume

Karahan Celikel - MSFT

It may help if you can turn on the WCF message tracing, and inspect the incoming and outgoing WCF messages. I would suggest creating a WCF client app that consumes your service, and after making sure that it works, compare the inbound/outbound WCF messages with the ones from the Biztalk scenario.

You can enable WCF message logging by having a app.config file in your WCF service similar to the following, and use SvcTraceViewer.exe to view the log.

< xml version="1.0" encoding="utf-8" >

<configuration>

<system.serviceModel>

<diagnostics performanceCounters="All">

<messageLogging

logEntireMessage="true"

logMalformedMessages="false"

logMessagesAtServiceLevel="true"

logMessagesAtTransportLevel="true"

maxMessagesToLog="300000"

maxSizeOfMessageToLog="200000"

/>

</diagnostics>

</system.serviceModel>

<system.diagnostics>

<sources>

<source name="System.ServiceModel.MessageLogging">

<listeners>

<add name="messages"

type="System.Diagnostics.XmlWriterTraceListener"

initializeData="c:\log.xml" />

</listeners>

</source>

</sources>

</system.diagnostics>

</configuration>

You can also modify the BTSNTSvc.exe.config file to enable the WCF message logging for BTS





Re: BizTalk R2 General wcf send port consume

mitre

hi Karahan,

thank you for the help! I'm getting closer. Looks like my XmlSerializerFormat attribute had gotten removed at some point. After adding it back in, the breakpoint on my service operation is hit . However the parameter I pass in, my schema instance is always null. .

The message log indicates the SoapBody contains the instance of my schema and the operation is clearly being called.

In order to get this to work in my own cliet, outside of biztalk, I had to change the classnames by hand from those generated by using svcUtil against the service. This doesn't resolve my problem with biztalk though as I have no idea how it is attempting to serialize the data being passed as a parameter, in this case it is acting as the client. Since I am not using an orchestration, and I can see the schema instance correctly desrialized in the log, why would I be getting a null for the parameter in the Operation Does this happen when a serialization issue occurrs I took the soapBody out and did a serialization of it into the object and that worked...





Re: BizTalk R2 General wcf send port consume

Karahan Celikel - MSFT

Mitre,

If your standalone client worked fine, can you compare the trace output from the client vs BizTalk

If the BizTalk outgoing message needs to be wrapped in an element, you can try using the template option on the send port to do that.

and also, the WSDL of the service might be helpful. The BizTalk scenario should work provided what BizTalk sends conforms to what the WSDL says.





Re: BizTalk R2 General wcf send port consume

mitre

Hi karahan,

Yes I compared the two.. The differences are at the schema and soap body level:

I noticed in my client version, the one that works the soap node has a namespace:

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

The biztalk version does not:

<s:Body>

Also in my client version, The schema is in the body is wrapped with the OperationName:

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<ProcessMyCompanyPOSell xmlns="http://MyCompany.com/Integration/Common/POSellProcess">
<MyCompanyPOSell bBatch="125" RefID="10">
.............
</s:Body>
in the biztalk version it's just the schema

<s:Body>

<MyCompanyPOSell bBatch="125" RefID="10" xmlns="http://MyCompany.com/Integration/Common/POSellProcess">

.............

</s:Body>

I'm not sure why my client wraps the schema with the operationName and moves the namespace of the schema instance up but it seems to work. I'll see if I can do this with the sendPort wrapping





Re: BizTalk R2 General wcf send port consume

Karahan Celikel - MSFT

Hi Mitre,

One of our developers referred me the following post about bare and wrapped parameters, which migh be helpful for your case.

http://blog.magenic.com/blogs/jeffk/archive/2007/06/18/Preserving-ASMX-web-service-contracts-in-WCF.aspx





Re: BizTalk R2 General wcf send port consume

mitre

Thanks for sharing,

This looks exactly like what I'm seeing. Does that mean that biztalk does not take this into account when sending an instance of a schema message over WCF basicHttp, we must use a messageContract on the service side That is it will not wrap the message by default

I was able to get this to work in some degree by using the Template feature you suggested to wrap the outbound message with the operation name. ie. I did the following in the outbound WCF messages template:

<ProcessMyCompanyPOSell xmlns="http://myCompany.com/Integration/Common/POSellProcess" >

<bts-msg-body xmlns="http://www.microsoft.com/schemas/bts2007" encoding="xml"/>

</ProcessMyCompanyPOSell>

The problem is when the message is returned in the response(should be the exact same message sent over in the request with value differences in the data), biztalk does not remove the wrapping node before handing off the message to the receieve pipleine on the request/response port.. This causes issues on the response to biztalk. So I get this back:

<ProcessMyCompanyPOSell xmlns="http://myCompany.com/Integration/Common/POSellProcess">

<myCompanyPOSell bBatch="125" RefID="10">

It looks like the xmlns was extracted from the real root and added to the wrapping as well.





Re: BizTalk R2 General wcf send port consume

mitre

Hi Karahan,

Think I've got this licked.. I used the messageContract method that was specified in the link you provided and after tweaking the generated class a bit, I was able to get this to work.

Thanks for your help