14 August, 2013

ESB Itinerary Deployment

Deploying itineraries to servers is currently one of those tasks I do just infrequently enough to forget the name of the tool to do it! When you don't want to - or can't - deploy straight to the itinerary DB from Visual Studio, you can use the ESBImportUtil in C:\Program Files\Microsoft BizTalk ESB Toolkit 2.0\Bin First up, in Visual Studio, set the "Model Exporter" property on the itinerary to "XML Itinerary Exporter". Then right click on the itinerary and choose "Export Model". This will create an XML itinerary file - VS usually opens the file and shows you the path where it is saved. You can then copy that file to C:\Program Files\Microsoft BizTalk ESB Toolkit 2.0\Bin on the server or computer you need to deploy the itinerary to. In a command window, browse to that location. You can then use the esbimportutil.exe tool to deploy it - for example: esbimportutil.exe /f:itinerary_file.xml /c:deployed /o Syntax for usage: /?: Help /f: Itinerary XML File Path /c: published | deployed /n: default itinerary name (seems to only work for itineraries exported in default mode) /v: default itinerary version /o: overwrite existing

08 March, 2011

EDI Toolkit 2.1 install - Exception calling "Create" with "0" argument(s): "Create failed for Login 'mydomain\BizTalk Server Administrators'."

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.

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.

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\"'

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().

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!

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