WS-AtomicTransaction issue in WCF Adapter
Hi,
I am trying to consume a WCF Service from a BizTalk Orchestration using the WCF Adapter with the Transaction enabled. I always get an error "No signature message parts were specified for messages with the * action". If I remove the line '[TransactionFlow(TransactionFlowOption.Mandatory)]' from the OperationContract and redo 'WCF Service consuming wizard' and re-import binding and run the orchestration, it works perfectly. Can anybody let me know if they have faced this issue with the WCF Adapter with TransactionFlow enabled and provide any solutions for the same? Thank you.
Steps to reproduce the problem:
1. Create a new WCF Service (File->New->Web site->WCF Service)
2. Edit the config file to Add a 'ServiceMetadata' in 'Service Behaviours' and set 'HttpGetEnabled' as True.
3. Edit the config file to add a 'new Binding configuration' and set 'TransactionFlow' as True and set the 'BindingConfiguration' in the Endpoint as the created Binding Configuration name.
4. Add the line '[TransactionFlow(TransactionFlowOption.Mandatory)]' for the MyOperation2 function
5. Build the WCF Service (If this WCF Service is tested from a .NET client, please invoke it within a TransactionScope).
6. Add a new BizTalk project and Use 'WCF Service Consuming Wizard' to import the WCF Service (by using Add Generated items).
7. Add a new Orchestration and Consume the WCF Service using the existing port type. Put the Send shape of WCF Adapter within an Atomic scope.
8. Build and deploy the BizTalk project.
9. Go to BizTalk Administration console import the bindings from the 'MyService.BindingInfo.xml' file (Notice that the imported send port has 'Enable Transactions' as checked).
10. Configure the ports and start the Orchestration.
11. When the Orchestration instance runs, notice that it does not complete and there is an error message in the event log saying "No signature message parts were specified for messages with the * action".
Thank you.
Hi Jon,
I was having the same issue and using the instructions you gave got past this. However I now have another issue:
When I try to use a flowed transaction service via BizTalk, I get the following:
The service operation requires a transaction to be flowed.
I have a .net client that works with the service just fine:
The code for the service is:
{
// Define a service contract.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Add(double n1, double n2);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Subtract(double n1, double n2);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Multiply(double n1, double n2);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Divide(double n1, double n2);
}
// Service class which implements the service contract.
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]
public class CalculatorService : ICalculator
{
[OperationBehavior(
TransactionScopeRequired = true)]
public double Add(double n1, double n2)
{
return n1 + n2;
}
[OperationBehavior(
TransactionScopeRequired = true)]
public double Subtract(double n1, double n2)
{
return n1 - n2;
}
[OperationBehavior(
TransactionScopeRequired = true)]
public double Multiply(double n1, double n2)
{
return n1 * n2;
}
[OperationBehavior(
TransactionScopeRequired = true)]
public double Divide(double n1, double n2)
{
return n1 / n2;
}
}
}
The working client looks like this:
{
// Create a client
CalculatorClient client = new CalculatorClient("ClientEndpoint");
using (TransactionScope ts = new TransactionScope(
TransactionScopeOption.RequiresNew))
{
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
ts.Complete();
}
//Closing the client gracefully closes the connection and cleans up resources
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
In BizTalk I have the enable transaction tickbox on the bindings tab set when I import the WCF service. One thing of interest to me is that fot the .net client when I run svcutil, the class generated is decorated as follows:
public interface ICalculator
{
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")]
[System.ServiceModel.TransactionFlowAttribute(System.ServiceModel.TransactionFlowOption.Mandatory)]
double Add(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")]
[System.ServiceModel.TransactionFlowAttribute(System.ServiceModel.TransactionFlowOption.Mandatory)]
double Subtract(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")]
[System.ServiceModel.TransactionFlowAttribute(System.ServiceModel.TransactionFlowOption.Mandatory)]
double Multiply(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")]
[System.ServiceModel.TransactionFlowAttribute(System.ServiceModel.TransactionFlowOption.Mandatory)]
double Divide(double n1, double n2);
}
However I can see no equivalent in BTS using the WCF import wizard, how is this happening under the covers and in BTS, how can I specify which sends are to be part of the same transaction... my assumption is that they have to be in the same atomic scope?
Many thanks
Andy