I use Enterprise Library 4.1 in a number of apps, and I'm glad that ESB Toolkit 2.0 uses it too. But I'm not so glad about the way ESBT handles its EntLib configuration. It does something the EntLib documents expressly say you should not do: tamper with EntLib configuration settings in machine.config.
When you install ESBT the MSI adds the following to machine.config:
<configSections>
...
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
...
</configSections>
...
<enterpriseLibrary.ConfigurationSource selectedSource="ESB File Configuration Source">
<sources>
<add name="ESB File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35" filePath="C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.0\esb.config"/>
<add name="ESB SSO Configuration Source" type="Microsoft.Practices.ESB.SSOConfigurationProvider.SSOConfigurationSource, Microsoft.Practices.ESB.SSOConfigurationProvider, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" applicationName="ESB" description="ESB SSO Configuration" contactInfo="someone@microsoft.com" userGroupName="BizTalk Application Users" adminGroupName="BizTalk Server Administrators"/>
</sources>
</enterpriseLibrary.ConfigurationSource>
(On a 64-bit machine, this will happen in both 32-bit and 64-bit versions of machine.config.)
What this does is, it forces Enterprise Library to ignore your app.config and/or web.config files and look for configuration information exclusively in ESBT's default configuration source, which happens to be the file "C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.0\esb.config". Since you probably didn't put your EntLib configuration settings in esb.config, EntLib won't find your apps' configuration at all, and they will crash. For example, a call to DatabaseFactory.CreateDatabase("myDatabase") will throw "System.Configuration.ConfigurationErrorsException: The requested database myDatabase is not defined in configuration."
I posted this on Microsoft's ESBT Forum yesterday and got a prompt response that led to a solution. Enterprise Library still looks in your app./web.config first, so if you insert your own <enterpriseLibrary.ConfigurationSource> section there, Enterprise Library will honor it.
So in my web.config file I inserted the following:
<configSections>
...
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
...
</configSections>
...
<enterpriseLibrary.ConfigurationSource selectedSource="Local File Configuration Source">
<sources>
<add name="Local File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.1.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35" filePath="web.config"/>
</sources>
</enterpriseLibrary.ConfigurationSource>
This causes Enterprise Library to look for my app's configuration settings in my web.config file once again, and thus my app works as it did before ESBT came along.
I'm even thinking that it's always a good idea to put a <enterpriseLibrary.ConfigurationSource> in every config file that uses Enterprise Library, since you never know when some joker is going to pull the same stunt as ESBT in machine.config.
This is not a totally joyous solution though, because the Enterprise Library Configuration Editor tool seems not to understand that different <enterpriseLibrary.ConfigurationSource> sections can exist in machine.config and web.config at the same time, and so it complains when I try to use it to edit my web.config.
For more details you can read the whole ESBT Forum thread here.
Showing posts with label BizTalk. Show all posts
Showing posts with label BizTalk. Show all posts
Friday, June 26, 2009
Sunday, June 7, 2009
Fixing BizTalk ENTSSO Failure on Windows Vista
I've been running BizTalk 2009 on my Windows Vista laptop, and suddenly today the Enterprise Single Sign-On Service stopped working. When I tried to start it manually, I got this error in the event log:
Could not create SSOSQL. To fix the problem, reinstall SSO or try 'regasm SSOSQL.dll' from a Visual Studio command prompt.
Error Code: 0x80131700
It turns out this error told me everything I needed to know -- except the location of SSOSQL.dll. Took me a little digging, but I found it here:
C:\Program Files\Common Files\Enterprise Single Sign-On\SSOSQL.dll
So, navigating to that folder in the Visual Studio Commmand prompt and running 'regasm SSOSQL.dll' fixed it right up.
The only lingering mystery is why the DLL got unregistered in the first place. I'm suspicious of Visual Studio 2010 Beta 1, which I installed yesterday. But I've got no proof of that.
(And yes, I do install a lot of goodies on my laptop.)
Could not create SSOSQL. To fix the problem, reinstall SSO or try 'regasm SSOSQL.dll' from a Visual Studio command prompt.
Error Code: 0x80131700
It turns out this error told me everything I needed to know -- except the location of SSOSQL.dll. Took me a little digging, but I found it here:
C:\Program Files\Common Files\Enterprise Single Sign-On\SSOSQL.dll
So, navigating to that folder in the Visual Studio Commmand prompt and running 'regasm SSOSQL.dll' fixed it right up.
The only lingering mystery is why the DLL got unregistered in the first place. I'm suspicious of Visual Studio 2010 Beta 1, which I installed yesterday. But I've got no proof of that.
(And yes, I do install a lot of goodies on my laptop.)
Tuesday, April 21, 2009
Enhancing the BizTalk Mapper: How to Wrap XSLT in Custom Functoids
I've published an article on this topic in the latest issue of BizTalk HotRod, the online magazine for BizTalk developers. It's at page 44.
http://biztalkhotrod.com/Documents/BizTalk_HotRod_Issue6_Q2_2009.pdf
In the article I describe a problem that's easy to solve using an Inline XSLT Call Template. Then I show how to turn the Inline XSLT Call Template into a custom functoid that can be deployed to the Mapper toolbox, so that developers with no XSLT knowledge can use it without seeing the script or writing any code.
http://biztalkhotrod.com/Documents/BizTalk_HotRod_Issue6_Q2_2009.pdf
In the article I describe a problem that's easy to solve using an Inline XSLT Call Template. Then I show how to turn the Inline XSLT Call Template into a custom functoid that can be deployed to the Mapper toolbox, so that developers with no XSLT knowledge can use it without seeing the script or writing any code.
Wednesday, April 15, 2009
BizTalk 2009 on my Laptop
Saturday, April 12, 2008
Fixing BizTalk's WCF Message Contract Mix-Up, Part 3
The final solution to the Message Contract Mix-Up doesn’t require you to define your own message contracts, but does require some tricks in both the operation contract and the BizTalk ports.
First, modify the operation contract by adding a MessageParameterAttribute to the argument and return type:
[OperationContract]
[return:MessageParameter(Name="OrderStatus")] PurchaseOrderStatus PlaceOrder([MessageParameter(Name="PurchaseOrder")]PurchaseOrder po);
MessageParameterAttribute lets you change the names that the parameter and return value will have in the SOAP body. The names need to be changed to “PurchaseOrder” and “OrderStatus” so BizTalk can associate the schemas PurchaseOrder.xsd and OrderStatus.xsd with those elements. (Without MessageParameterAttribute, WCF would force the names of the parameter and return value to be “po” and “PlaceOrderResult”, which mean nothing to BizTalk).
Now you need to modify the WCF adapter settings in the two-way receive location in BizTalk. For general instructions and screenshots illustrating the following steps see the BizTalk documentation here. Open the Messages tab of the WCF adapter. Under “Specify the source of the inboud BizTalk message body”, check the third radio button, “Path – content located by body path”. In the text box type an XPATH expression consisting of the name of your operation contract, followed by the name of your data contract schema:
/*[local-name()='PlaceOrder']/*[local-name()='PurchaseOrder']
Make sure the combo box below the text box, “Node encoding”, is set to XML.
The first element in the XPATH is actually the WCF-generated message contract, which has the same name as the operation contract (“PlaceOrder”). The following element is the name of the parameter inside the message contract, which we forced to be “PurchaseOrder” by applying the MessageParameterAttribute.
The consequence of these settings is that the WCF adapter will drill through the message contract and pass the PurchaseOrder element to BizTalk as the message body. Bingo!
Since this is a two-way port, we need to return a data contract back to the caller, and to do that we need to tell the WCF adapter how to wrap the data contract inside a message contract. To do that, go to the bottom half of the tab and check “Template – content specified by template.” In the text box below, be careful not to delete or change the bts-msg-body element that’s already there, since that represents the data contract part of the message. Instead, insert an XML element around the bts-msg-body to represent the message contract. The name of this element is the operation contract’s name plus the suffix “Response”, and it must include the correct XML namespace:
<PlaceOrderResponse xmlns="urn://MyCompany.Purchasing.1_0_0.com" >
<bts-msg-body xmlns="http://www.microsoft.com/schemas/bts2007" encoding="xml" >
</PlaceOrderResponse >
If this were a one-way send port we would follow the same procedure.
The result is that BizTalk will send the return value to client wrapped inside the same message contract that WCF would have generated automatically if the service were hosted in a pure .NET application. Bingo Bingo!
So there you have three ways to solve the Message Contract Mix-Up with the BizTalk WCF adapters. If you’ve read all the way through this series, I surmise that you either find the subject fascinating, or you need to solve these problems as badly as I did.
First, modify the operation contract by adding a MessageParameterAttribute to the argument and return type:
[OperationContract]
[return:MessageParameter(Name="OrderStatus")] PurchaseOrderStatus PlaceOrder([MessageParameter(Name="PurchaseOrder")]PurchaseOrder po);
MessageParameterAttribute lets you change the names that the parameter and return value will have in the SOAP body. The names need to be changed to “PurchaseOrder” and “OrderStatus” so BizTalk can associate the schemas PurchaseOrder.xsd and OrderStatus.xsd with those elements. (Without MessageParameterAttribute, WCF would force the names of the parameter and return value to be “po” and “PlaceOrderResult”, which mean nothing to BizTalk).
Now you need to modify the WCF adapter settings in the two-way receive location in BizTalk. For general instructions and screenshots illustrating the following steps see the BizTalk documentation here. Open the Messages tab of the WCF adapter. Under “Specify the source of the inboud BizTalk message body”, check the third radio button, “Path – content located by body path”. In the text box type an XPATH expression consisting of the name of your operation contract, followed by the name of your data contract schema:
/*[local-name()='PlaceOrder']/*[local-name()='PurchaseOrder']
Make sure the combo box below the text box, “Node encoding”, is set to XML.
The first element in the XPATH is actually the WCF-generated message contract, which has the same name as the operation contract (“PlaceOrder”). The following element is the name of the parameter inside the message contract, which we forced to be “PurchaseOrder” by applying the MessageParameterAttribute.
The consequence of these settings is that the WCF adapter will drill through the message contract and pass the PurchaseOrder element to BizTalk as the message body. Bingo!
Since this is a two-way port, we need to return a data contract back to the caller, and to do that we need to tell the WCF adapter how to wrap the data contract inside a message contract. To do that, go to the bottom half of the tab and check “Template – content specified by template.” In the text box below, be careful not to delete or change the bts-msg-body element that’s already there, since that represents the data contract part of the message. Instead, insert an XML element around the bts-msg-body to represent the message contract. The name of this element is the operation contract’s name plus the suffix “Response”, and it must include the correct XML namespace:
<PlaceOrderResponse xmlns="urn://MyCompany.Purchasing.1_0_0.com" >
<bts-msg-body xmlns="http://www.microsoft.com/schemas/bts2007" encoding="xml" >
</PlaceOrderResponse >
If this were a one-way send port we would follow the same procedure.
The result is that BizTalk will send the return value to client wrapped inside the same message contract that WCF would have generated automatically if the service were hosted in a pure .NET application. Bingo Bingo!
So there you have three ways to solve the Message Contract Mix-Up with the BizTalk WCF adapters. If you’ve read all the way through this series, I surmise that you either find the subject fascinating, or you need to solve these problems as badly as I did.
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. 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.
Fixing BizTalk's WCF Message Contract Mix-Up, Part 1
WCF developers often write OperationContracts that receive and return DataContracts, like so:
[ServiceContract(Namespace = "urn://MyCompany.Purchasing.1_0_0.com")]
public interface IPurchasing
{
[OperationContract]
OrderStatus PlaceOrder(PurchaseOrder po);
}
Suppose you implement this service in BizTalk using an orchestration. First you use a tool such as XSD.exe or SVCUtil.exe to generate XSD schemas for the PurchaseOrder and OrderStatus data contracts. You add these schemas to a BizTalk project, write an orchestration that receives a PurchaseOrder and returns an OrderStatus, and deploy the schemas and orchestration to BizTalk. Then you bind the orchestration’s receive-send port to a two-way receive location using a WCF adapter and the XmlReceive pipeline.
Your may be shocked to find that when a WCF client sends a message to BizTalk, an error occurs in the receive pipeline: “Finding the document specification by message type "urn://MyCompany.Purchasing.1_0_0.com #PlaceOrder" failed. Verify the schema deployed properly.”
It turns out that the SOAP body that your WCF client sent to BizTalk doesn’t begin with the PurchaseOrder data contract. Instead it begins with a message contract that the WCF client generated behind the scenes. The name of this message contract is “PlaceOrder”, i.e. the name of the operation. Inside that message contract is an element named “po” which contains the data exposed by the data contract. Thus although BizTalk expects to receive a message type named PurchaseOrder, there is no element named PurchaseOrder anywhere in the SOAP body!
There's a symmetrical problem at the other end, when the two-way receive port tries to return an OrderStatus to the caller. If the service were hosted in a .NET application, WCF would automatically generate a message contract element named PlaceOrderResponse and wrap it around the OrderStatus. But BizTalk by default will do no such thing.
I call this impedence mismatch the "BizTalk WCF Message Contract Mix-Up". But so much for lingo, how do you fix it? I can suggest three solutions, each with its pros and cons. I’ll discuss them in the next post.
[ServiceContract(Namespace = "urn://MyCompany.Purchasing.1_0_0.com")]
public interface IPurchasing
{
[OperationContract]
OrderStatus PlaceOrder(PurchaseOrder po);
}
Suppose you implement this service in BizTalk using an orchestration. First you use a tool such as XSD.exe or SVCUtil.exe to generate XSD schemas for the PurchaseOrder and OrderStatus data contracts. You add these schemas to a BizTalk project, write an orchestration that receives a PurchaseOrder and returns an OrderStatus, and deploy the schemas and orchestration to BizTalk. Then you bind the orchestration’s receive-send port to a two-way receive location using a WCF adapter and the XmlReceive pipeline.
Your may be shocked to find that when a WCF client sends a message to BizTalk, an error occurs in the receive pipeline: “Finding the document specification by message type "urn://MyCompany.Purchasing.1_0_0.com #PlaceOrder" failed. Verify the schema deployed properly.”
It turns out that the SOAP body that your WCF client sent to BizTalk doesn’t begin with the PurchaseOrder data contract. Instead it begins with a message contract that the WCF client generated behind the scenes. The name of this message contract is “PlaceOrder”, i.e. the name of the operation. Inside that message contract is an element named “po” which contains the data exposed by the data contract. Thus although BizTalk expects to receive a message type named PurchaseOrder, there is no element named PurchaseOrder anywhere in the SOAP body!
There's a symmetrical problem at the other end, when the two-way receive port tries to return an OrderStatus to the caller. If the service were hosted in a .NET application, WCF would automatically generate a message contract element named PlaceOrderResponse and wrap it around the OrderStatus. But BizTalk by default will do no such thing.
I call this impedence mismatch the "BizTalk WCF Message Contract Mix-Up". But so much for lingo, how do you fix it? I can suggest three solutions, each with its pros and cons. I’ll discuss them in the next post.
BizTalk WCF Adapters: OneWay to Nowhere
Newcomers to the WCF Adapters in BizTalk Server 2006 R2 must be aware of two “gotchas” that they're likely to face when sending or receiving WCF messages with the adapters.
The first gotcha is that the IsOneWay property of operation contracts must be false. Luckily IsOneWay is false by default, but developers sometimes set it to true in an attempt to improve performance.
But the BizTalk WCF adapters always set IsOneWay to false, and so will fail whenever sending to or receiving from a client or service that has IsOneWay = true. (There’s an exception for the NetMsmq adapter.) Details about the errors you’ll receive are in the BizTalk documentation here.
The simple solution is to set IsOneWay back to false on your client or service. If you’re able to do that, the problem goes straight away.
If not – if for instance you lack authority to change the service contract – then you’ll have to put a wrapper service between BizTalk and the real service which, you guessed it, has the same WCF contracts as the real service except that IsOneWay is always false. This can be a pain, though it’s not hard to understand what you’re doing.
The second gotcha requires some deeper knowledge of WCF, so I’ll save it for the next post.
The first gotcha is that the IsOneWay property of operation contracts must be false. Luckily IsOneWay is false by default, but developers sometimes set it to true in an attempt to improve performance.
But the BizTalk WCF adapters always set IsOneWay to false, and so will fail whenever sending to or receiving from a client or service that has IsOneWay = true. (There’s an exception for the NetMsmq adapter.) Details about the errors you’ll receive are in the BizTalk documentation here.
The simple solution is to set IsOneWay back to false on your client or service. If you’re able to do that, the problem goes straight away.
If not – if for instance you lack authority to change the service contract – then you’ll have to put a wrapper service between BizTalk and the real service which, you guessed it, has the same WCF contracts as the real service except that IsOneWay is always false. This can be a pain, though it’s not hard to understand what you’re doing.
The second gotcha requires some deeper knowledge of WCF, so I’ll save it for the next post.
Subscribe to:
Posts (Atom)

