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