I needed to install the EDI toolkit 2.1 on a distributed BizTalk environment (SQL on one box, BizTalk app server on another). When I came to run the EDI toolkit configuration tool to set up the exception database, the error I got was:
Exception calling "Create" with "0" argument(s): "Create failed for Login 'MY DOMAIN\BizTalk Server Administrators'."
On my SQL server, the login for that group was configured as "domain\BizTalk Server Administrators".
By changing the SQL login to make the domain upper case ("DOMAIN"), the issue was resolved.
08 March, 2011
03 November, 2010
Dynamic WCF endpoint in BizTalk 2006 R2 with SSL and client certs
I had a requirement to submit a message to a WCF web service, but the target endpoint was dependent upon a value supplied in the initiating message. This work was done within an orchestration. The solution required the web service request to be sent over SSL, using client certificates for message authorisation.
The target URL was promoted as a distinguished property (called Url) in a message "CallbackUrl".
I had already consumed the target WCF service in my BizTalk project, so in my orchestration I added a new request-response port (MyPort), using the port type generated during that process. However, I configured the port to be dynamic.
In a message assignment shape, I created the message (MyMsg) to submit to the service. Then I configured the dynamic WCF bindings as below:
-------------------------------------------------------------------------------------
MyMsg(WCF.BindingType) = "basicHttpBinding";
MyMsg(WCF.EndpointBehaviorConfiguration) = "<behavior name=\"EndpointBehavior\"><clientCredentials><clientCertificate findValue=\"requiredCertName\" storeLocation=\"CurrentUser\" storeName=\"My\" x509FindType=\"FindBySubjectName\" /></clientCredentials></behavior>";
MyMsg(WCF.BindingConfiguration) = "<binding name=\"basicHttpBinding\" closeTimeout=\"00:05:00\" openTimeout=\"00:05:00\" sendTimeout=\"00:05:00\" maxBufferSize=\"650536\" maxReceivedMessageSize=\"650536\"><security mode=\"Transport\"><transport clientCredentialType=\"Certificate\" /><message clientCredentialType=\"Certificate\" /></security></binding>";
MyMsg(WCF.OutboundBodyLocation) = "UseBodyElement";
MyMsg(WCF.InboundBodyLocation) = "UseBodyElement";
MyMsg(WCF.PropagateFaultMessage) = true;
MyMsg(WCF.SuspendMessageOnFailure) = true;
MyPort(Microsoft.XLANGs.BaseTypes.Address) = CallbackUrl.Url;
MyPort(Microsoft.XLANGs.BaseTypes.TransportType) = "WCF-Custom";
------------------------------------------------------------------------------------
If you start with a working static port, you can export the bindings for the port and use the XML to populate the WCF.EndpointBehaviorConfiguration and WCF.BindingConfiguration properties.
In reality, the client certificates required were different for each target URL, so the certificate name was held against the URL in a config file and read in using a helper class. But to make the sample code above more straightforward, I've just hard-coded the certificate name.
The key to getting this working is that the public and private keys of the client certificate must be accessible by the account the BizTalk host instance runs under - if you're using a self-signed cert for testing. For production, the BizTalk host instance just needs access to the public key. Log on to the computer as the host account and import the certs into the "personal" folder in MMC.
The target URL was promoted as a distinguished property (called Url) in a message "CallbackUrl".
I had already consumed the target WCF service in my BizTalk project, so in my orchestration I added a new request-response port (MyPort), using the port type generated during that process. However, I configured the port to be dynamic.
In a message assignment shape, I created the message (MyMsg) to submit to the service. Then I configured the dynamic WCF bindings as below:
-------------------------------------------------------------------------------------
MyMsg(WCF.BindingType) = "basicHttpBinding";
MyMsg(WCF.EndpointBehaviorConfiguration) = "<behavior name=\"EndpointBehavior\"><clientCredentials><clientCertificate findValue=\"requiredCertName\" storeLocation=\"CurrentUser\" storeName=\"My\" x509FindType=\"FindBySubjectName\" /></clientCredentials></behavior>";
MyMsg(WCF.BindingConfiguration) = "<binding name=\"basicHttpBinding\" closeTimeout=\"00:05:00\" openTimeout=\"00:05:00\" sendTimeout=\"00:05:00\" maxBufferSize=\"650536\" maxReceivedMessageSize=\"650536\"><security mode=\"Transport\"><transport clientCredentialType=\"Certificate\" /><message clientCredentialType=\"Certificate\" /></security></binding>";
MyMsg(WCF.OutboundBodyLocation) = "UseBodyElement";
MyMsg(WCF.InboundBodyLocation) = "UseBodyElement";
MyMsg(WCF.PropagateFaultMessage) = true;
MyMsg(WCF.SuspendMessageOnFailure) = true;
MyPort(Microsoft.XLANGs.BaseTypes.Address) = CallbackUrl.Url;
MyPort(Microsoft.XLANGs.BaseTypes.TransportType) = "WCF-Custom";
------------------------------------------------------------------------------------
If you start with a working static port, you can export the bindings for the port and use the XML to populate the WCF.EndpointBehaviorConfiguration and WCF.BindingConfiguration properties.
In reality, the client certificates required were different for each target URL, so the certificate name was held against the URL in a config file and read in using a helper class. But to make the sample code above more straightforward, I've just hard-coded the certificate name.
The key to getting this working is that the public and private keys of the client certificate must be accessible by the account the BizTalk host instance runs under - if you're using a self-signed cert for testing. For production, the BizTalk host instance just needs access to the public key. Log on to the computer as the host account and import the certs into the "personal" folder in MMC.
Getting the font right in HTML emails (for fussy clients)
It's been a while since I wrote any HTML in anger, so I'm probably a bit behind the times... The other day a client insisted that all comms sent to them were in verdana, 10pt. This included a notification email sent from BizTalk. To force Outlook to display the font as verdana 10pt, setting the font in an old-school font tag didn't do the trick. Using a span tag instead solved the problem:
span style='font-family:\"Verdana\",\"sans-serif\";font-size:\"10pt\"'
span style='font-family:\"Verdana\",\"sans-serif\";font-size:\"10pt\"'
26 October, 2010
Unit Testing Peskiness
Long time, no post, but I'm back. At least for this one note to self that I know I'll forget later.
So, let's say you're creating unit tests in VS2010 with MSTest. Let's also say that you're checking your code coverage along the way to watch your progress, and let's also say that there's always a pesky percentage point or 2 that comes up as Not Covered and just greatly inhibits the joy you'd like to be experiencing by seeing 100% code coverage.
What's more, let's say that those uncovered portions are always in Visual Studio generated code for 'MySettings', and you're not using 'MySettings', so you have no need to test 'MySettings'.
There is a handy-dandy attribute that can exclude bits from code coverage calculations, called logically enough: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute().
So, let's say you're creating unit tests in VS2010 with MSTest. Let's also say that you're checking your code coverage along the way to watch your progress, and let's also say that there's always a pesky percentage point or 2 that comes up as Not Covered and just greatly inhibits the joy you'd like to be experiencing by seeing 100% code coverage.
What's more, let's say that those uncovered portions are always in Visual Studio generated code for 'MySettings', and you're not using 'MySettings', so you have no need to test 'MySettings'.
There is a handy-dandy attribute that can exclude bits from code coverage calculations, called logically enough: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute().
13 August, 2010
Idle Friday afternoon ranting...
We did mention this blog would feature food, grief management and various assorted oddities as well as software development so...
Curiously (and it's okay, I am planning to see a doctor), I am in no mood for chocolate. Even after a 13 hour marathon yesterday related to an expired root certificate:
Customer: Send me the certificate you're talking about
Me:
Customer: Try this one
Me: Er, this looks the same as the one I just sent you that doesn't work
Customer: Yes
Me: Errrr.....
(2000 unsent messages, 13 hours, 10 people and some hysterical laughter - on my part - later... workaround agreed on and implemented until root cert renewed)
Anyways, I can attest to the fact that Kokako bliss balls are quite a tasty, healthy alternative to chocolately treats. They have dates, figs, maple syrup, cocoa, sunflower seeds... The kind of stuff that would make Ross roll his eyes and reach for a two litre bottle of Coke (although his eyes did unglaze briefly at the mention of maple syrup and cocoa... well, they would have... if he was around to amuse me for the remainder of this work day... Probably too busy drinking tequila in Mexico - the world IS unfair, kids...) Roll on the weekend!
Curiously (and it's okay, I am planning to see a doctor), I am in no mood for chocolate. Even after a 13 hour marathon yesterday related to an expired root certificate:
Customer: Send me the certificate you're talking about
Me:
Customer: Try this one
Me: Er, this looks the same as the one I just sent you that doesn't work
Customer: Yes
Me: Errrr.....
(2000 unsent messages, 13 hours, 10 people and some hysterical laughter - on my part - later... workaround agreed on and implemented until root cert renewed)
Anyways, I can attest to the fact that Kokako bliss balls are quite a tasty, healthy alternative to chocolately treats. They have dates, figs, maple syrup, cocoa, sunflower seeds... The kind of stuff that would make Ross roll his eyes and reach for a two litre bottle of Coke (although his eyes did unglaze briefly at the mention of maple syrup and cocoa... well, they would have... if he was around to amuse me for the remainder of this work day... Probably too busy drinking tequila in Mexico - the world IS unfair, kids...) Roll on the weekend!
10 August, 2010
XSLT namespace fun in scripting functoids
Another thing I frequently forget...
To find the namespace prefix to use in a scripting functoid in a map, right click on the map, select "validate map" and view the resulting xsl file. The opening stylesheet tag should show you which namespace prefixes apply to each input message (eg. s0 / s1).
If you're using aggregate schemas (particularly if you changed an existing map to use an aggregate input schema), you may now need to include the root node name in your XSLT. For example, if you have a message
<?xml:namespace prefix="ns0" /><ns0:request ns0="http://myschema">
<ns0:order>
<ns0:id>1234</ns0:id>
</ns0:order>
</ns0:request>
and you previously referenced the ID element using s0:order/so:id
you may now need to reference it using //s0:Request/s0:order/so:id
To find the namespace prefix to use in a scripting functoid in a map, right click on the map, select "validate map" and view the resulting xsl file. The opening stylesheet tag should show you which namespace prefixes apply to each input message (eg. s0 / s1).
If you're using aggregate schemas (particularly if you changed an existing map to use an aggregate input schema), you may now need to include the root node name in your XSLT. For example, if you have a message
<?xml:namespace prefix="ns0" /><ns0:request ns0="http://myschema">
<ns0:order>
<ns0:id>1234</ns0:id>
</ns0:order>
</ns0:request>
and you previously referenced the ID element using s0:order/so:id
you may now need to reference it using //s0:Request/s0:order/so:id
29 July, 2010
VB IsDate equivalent in C#
Now I'm living in a C# world... and my memory fails me every time I need to do this (which frankly, says worrying things about my memory)... DateTime.TryParse returns a boolean indicating whether the input string can be converted to a datetime or not. So you can write a wee function like the following:
public Boolean checkDate(string inputDate)
{
Boolean retValue = false;
DateTime outputDate;
if (DateTime.TryParse(inputDate, out outputDate))
{
retValue = true;
}
return retValue;
}
public Boolean checkDate(string inputDate)
{
Boolean retValue = false;
DateTime outputDate;
if (DateTime.TryParse(inputDate, out outputDate))
{
retValue = true;
}
return retValue;
}
Subscribe to:
Posts (Atom)