Entries in BizTalk (10)


Microsoft Dynamics AIF Error, missing class attribute

Came across a rather annoying issue that caused a few people to scratch their heads. We were integrating with AX using BizTalk and sending in a standard SalesOrder message but it kept failing with the following error:

Error:    The class AxSalesTableInterface does not support or does not have a parmSalesLineInterface method.
Error: Data source SalesPrice not in query AxdSalesOrderInterface.

After some sole searching we remembered that within the BizTalk map we had to use some custom XSLT to deal with some aggregation.

<xsl:template name="f_GiftLineItems">
<xsl:param name="totalLines" />
<xsl:param name="index" />

<xsl:if test="1 = ($index)">
<xsl:element name="ns0:SalesLineInterface">
<xsl:element name="ns0:ItemId">GIFT1</xsl:element>

<xsl:element name="ns0:SalesPrice">
<xsl:value-of select="userCSharp:MathRound(sum(//*[local-name()='Detail']/@GiftWrapPrice),'2')"/>

<xsl:element name="ns0:QtyReserved">1</xsl:element>

<xsl:element name="ns0:SalesLineInterface">
<xsl:element name="ns0:ItemId">SHIP6</xsl:element>

<xsl:element name="ns0:SalesPrice">
<xsl:value-of select="userCSharp:MathRound(sum(//*[local-name()='Detail']/@ShippingPrice),'2')"/>

<xsl:element name="ns0:QtyReserved">1</xsl:element>


The SalesLineInterface has an attribute called class that is required and must contain the string “entity”. The BizTalk mapper will normally add the attribute for us but as we’d used the Script Functoid we have to explicitly add it.  Easy to miss and can take a while to work out what’s going on. The class attribute is present on all “table” records in the AIF message and needs to be there.


<xsl:element name="ns0:SalesLineInterface">
<xsl:attribute name="class"><xsl:text>entity</xsl:text></xsl:attribute>

BizTalk Integrations with Salesforce.com, Part 2

This is a follow up to my original post on setting up SalesForce.com with a custom API to call from BizTalk and leverage some new functionality like the SandBox feature. This time we will focus on setting up BizTalk to call the Web Service we configured earlier.

The source code can be downloaded here.

SalesForce.com Security

Before we start you’ll need the security token that SFDC should have emailed you. You can request it again from the Setup/[My Personal Information]/[Reset your security token].


We’ll need this to request a SessionID or access token from SFDC before the web service call. Richard Seroter already came up with a solution to this so we’ll just reuse that here.

You’ll also need to download the Enterprise WSDL from force.com.

1.  Logon to SDFC

2.  Navigate to Setup, Develop & API and click on [Generate Enterprise WSDL]


3.  Save this with the WSDL we generated from the previous post.

4.  Create a Helpers project and add a web reference to using the Enterprise WSDL we just downloaded.

5. Add a class with the following:

/// <summary>
/// For more information see: http://bit.ly/jKmt73
/// </summary>
public class ForceToken
private static DateTime _sessionDate = DateTime.Now;
private static string _sessionId = string.Empty;

public static string SessionId
get { return GetSession(); }
private static string GetSession()
DateTime now = DateTime.Now;
TimeSpan diff = now.Subtract(_sessionDate);
if (_sessionId == string.Empty || (diff.Minutes > 60))
//TODO lock object during update
//refresh token
"Salesforce.com Session Refresh");
string uname = "shaycarl@synthesisconsulting.net";
string password = "rocktard";
string securityToken = "vGjbtdjuA7nUCVQSjNYC4SvK4";
SFSvcRef.SforceService proxy = new SFSvcRef.SforceService();
proxy.Url = "https://www.salesforce.com/services/Soap/c/20.0";

SFSvcRef.LoginResult result = proxy.login(uname, password + securityToken);

"Salesforce.com Session Refresh completed with id: " + result.sessionId);

_sessionId = result.sessionId;
return _sessionId;

In BizTalk we’re going to call this method from an expression shape. As you can see the tokens expire so we’ll request a new one every hour.

This is where you’ll paste in your security token, username and password. 

BizTalk Orchestration

Next we’ll create an orchestration that calls our custom SFDC API. We’ll cheat a little and just use the messages as defined in the WSDL.

The orchestration will be bound to a receive port (FILE), it’ll call the ForceToken.GetSession() method above, figure out what action is required (update, insert etc) and finally call our API.

1.  To get started we first need to import the custom API WSDL. To do this right click your project and select [Add Generated Item] then choose [Consume WCF Service] and give it the WSDL for our custom API.


This will create all our schemas, multipart messages, port types and generate a Bindings file that we can use to create our WCF-Custom send port.


2.  Add an Orchestration to the project and setup a configured receive port and an activating receive shape. This message will just be an XmlDocument so we can generically handle all the API functions.

3.  Next add an expression shape where we’ll call out to get our SessionID. We’re also going to need the root element to determine what API we need to call.

root = xpath(msgIn, "string(local-name(/*))");
sessionId = Sfdc.Helper.ForceToken.SessionId;

4.   Drag on a Decide shape and setup the following branches.


// Get Branch
root == "GetContact"

// Insert Branch
root == "AddContact"

// Update Branch
root == "UpdateContact"

5.  For each branch we’ll instantiate the appropriate API message and setup the Header with the SessionID.

msgGetContact.parameters = msgIn;
msgGetContact(WCF.Headers) =
+ sessionId

This will be the same for each branch except for the Add function. To add a contact we first need to retrieve the AccountID based on the AccountName provided. To achieve this we’ll construct a GetAccountId message, call the API and map the response plus our original request to the InsertContact API message.

msgAddAcct = msgIn;
xmlDoc.LoadXml("<ns0:GetAccountId xmlns:ns0=\"http://soap.sforce.com/schemas/class/BtsWebService\">
msgGetAcctId.parameters = xmlDoc;
msgGetAcctId.parameters.accountName = msgAddAcct.AccountName;
msgGetAcctId(WCF.Headers) =
+ sessionId


Input Messages

Once you’ve got all this together you should be able to call the SFDC API and start adding contacts. The messages you submit to BizTalk would look something like this:

Insert a contact

<ns0:AddContact xmlns:ns0="http://Sfdc.Bts.AddContact">
<AccountName>Synthesis Consulting, Inc</AccountName>
Note: This is a custom message as we need the AccountName not the AccountID

Retrieve a contact

<ns0:GetContact xmlns:ns0="http://soap.sforce.com/schemas/class/BtsWebService">

Update a contact

<ns0:UpdateContact xmlns:ns0="http://soap.sforce.com/schemas/class/BtsWebService">

With the exception of the SessionID it’s all pretty straight forward and even that isn’t terribly difficult. After about an hours work we got our SalesForce.com instance setup with a custom API and developed an integration solution (albeit a very simple solution) using BizTalk, pretty sweet.

Apart from Seroter Steef-Jan Wiggers has a few good posts on integrating with SalesForce.com using BizTalk & MSMQ that is probably worth checking out.


BizTalk Integrations with Salesforce.com

This is almost a part 2 of Richard Seroter’s post on the same topic. What I have done here is expand on the details in that post and I am also making the sample code available. It seems things on force.com have changed; the biggest difference is using the sandbox environment and then publishing that to production SFDC environment.

Extra Info: As part of this setup I also uninstalled the default packages that SFDC sample site contains just to keep things simpler. These can be uninstalled from Setup screen under App Setup –> View Installed Packages. They also contain a number of APEX web classes and I removed these as I was trying to get the proper test coverage for my own web services and make these simpler.

Salesforce.com Configuration


Account Creation and Home Page Customization

1.  First thing to do is go and sign up for a free force.com account at http://www.salesforce.com/platform/platform-edition/. After signing up, you can customize your account.

2.  Since we are going to work with contacts, go ahead and add a Contacts and Account tab to your home page. Click on the + sign next to “Get Started” to take you to the “All Tabs” page.


3.  From the “All Tabs” page, select “Customize My Tabs.” This navigates to a screen where you can add contacts and accounts so it appears on the home page tabs.


4.  Click on the Accounts tab and select All Accounts.

5.  Create a new account by clicking on the New Account button and give the Account a name of ‘Synthesis Consulting Inc.’ We will need this account later on when testing our web services operations.

Adding Custom Fields and Uninstalling packages

In this next, Contacts will be customized, by adding a Global Id field. Again kudos to Richard for having a blog on this. He does a few more columns; here are similar steps for adding Global Id to the Contact object.

1.  From Salesforce.com, go to the Setup section.

Tip: For quite a while I went there through a convoluted manner until I found out that I could just click the arrow next to my user name in the upper right and select ‘Setup.’ From the setup screen you will be able to do a number of activities that are necessary to get the Web Services up and running on SFDC. This includes, adding custom fields, creating a Sandbox environment, creating the APEX API class and related Test methods, deploying those to ‘production,’ and generating a WSDL.

2.  Navigate to to App Setup –> Customize –> Contacts –> Fields


3.  Scroll to the bottom of the fields page to see Custom Fields and select New.

4.  Select ‘Text’ for the Data Type. Click Next.

5.  Enter the following information for Global Id and click Next.

Field Label

Global Id



Field Name





Checked, case insensitive

External ID


6.  For field-level security, click Next.

7.  For page layouts, click Save.



Create a Sandbox Environment

Now that a Global Id for Contacts has been added the web services can be created. SFDC does not allow you to create web services directly in the ‘production’ environment. Instead, they are created in a sandbox environment and then promoted into the production environment. These steps will show how to create the sand box environment.

1.  On the left side of the screen navigate to Administration Setup –> Data Management –> Sandbox.

2.  Click on “New Sandbox.”

3.  Enter a name for the Sandbox environment, leave other defaults and click “Start Copy.” At this point SFDC will begin creating a copy of the SFDC environment.


4.  Once it is complete, click on the ‘Sandbox’ link again. Click on the login link to be taken to a new login screen. It will have your existing login with a suffix of ‘.<Sandbox Name>.’ E.g. myuser@hotmail.com.BlogExampl.

Tip: Opening this login window in a new tab will allow you to stay logged into both environments which will come in handy when you go to create a connection between the environments.

5.  Login Into SandBox using your existing password.


Create APEX API Class and Test Methods

Now that we have a sandbox, we can go create our APEX API Classes. APEX is SalesForce own programming language, but resembles C#. To create web services we can call from BizTalk, a APEX class and methods will be created corresponding to a web service and related operations.

1. Assuming you’re a logged into your Sandbox environment, create a new APEX Class by navigating to App Setup –> Develop –> Apex Classes. Then click New.


2.  The brings you to a window where you can type in your new Apex Class. It you are used to an IDE like Visual Studio or Eclipse, this is a far cry from anything like that. SFDC does provide a Force.com IDE that you can download and install from here. This does give you a much richer environment, but if you want to debug your code you have to have it in the cloud. Similar experience to what you might find with BizTalk Orchestrations. <Azure Plug>I’m glad though Microsoft allows you to debug locally with Azure using Windows Azure Development Fabric.</Azure Plug>  Getting back to the topic, for the new class copy and paste the following code:

global class BtsWebService 
webService static Contact GetContact(String globalId)
Contact c1 = [ SELECT c.GlobalId__c, c.FirstName, c.LastName,
c.MailingCity, c.MailingPostalCode, c.MailingState
FROM Contact c
WHERE c.GlobalId__c = :globalId LIMIT 1];
return c1;

webService static Id InsertContact(String lName, String acctId, String globalId)
Contact c = new Contact(lastName = lName, AccountId = acctId,
GlobalId__c = globalId);
insert c;
return c.Id;

webService static Contact UpdateContact(String globalId, String lName)
Contact c = [SELECT account.name FROM contact
WHERE globalId__c = :globalId limit 1];
c.lastName = lName;
update c;
return c;

webService static Id GetAccountId(String accountName)
Account a = [SELECT Id FROM Account WHERE Name = :accountName limit 1];
return a.Id;

This will provide a web service with four very simple methods that we can call.

3.  Click Save. This will validate the service and provide you a page to work with the new service, BtsWebService.

4.  Click on “Apex Classes” where we will add another class to test our Web Service. Click New and add cut and paste the following code:


private class BtsWebServiceTest {

static testMethod void testGetContact()

Account a = [Select a.Name, a.Id From Account a WHERE a.Name = 'Synthesis Consulting, Inc' LIMIT 1];

String lName = 'Smith';
String globalId = 'Bts1002';

Id aId = BtsWebService.GetAccountId(a.Name);
Id cId = BtsWebService.InsertContact(lName, aId, globalId);

Contact myContact= BtsWebService.GetContact(globalId);
Contact myContact2 = BtsWebService.UpdateContact(myContact.GlobalId__c, lName + 's');

System.debug('***** id1:' + myContact.Id);
System.debug('***** id2:' + myContact2.Id);
System.debug('***** Name1:' + myContact.LastName);
System.debug('***** Name2:' + myContact2.LastName);

String id1 = myContact.Id;
String id2 = myContact2.Id;
System.assertEquals(id1, id2);
System.assertEquals(lName + 's', myContact2.LastName);


There are lots of improvements that can be made with this class, but this gets the job done providing a method that exercises all of our classes. SFDC requires that we have certain amount of test coverage over the Apex classes. If you have improvements to this test class, feel free to let me know.

5.  Click Save and then click Run to test the web service. It should run successfully. At this point the changes to the Sandbox can be promoted to the production environment.



Publish the Classes to SFDC Production

In order to promote these APEX classes into production the relationship needs to be created between the two environments and then the changes need to be published into the production environment.

1.  Go to the production environment, either another browser tab, or if you closed it, log into your production environment again. Keep the Sandbox environment browser window open as we will go back to that shortly.

2.  In the production environment go to Setup and navigate to App Setup –> Deploy –> Deployment Connections.

3.  Click Edit and check the box to allow Inbound connection from BlogExampl (my Sandbox instance) and click Save. This will allow changes from the Sandbox to be deployed to Production.


4.  From the Sandbox environment, click on App Setup –> Deploy –> Outbound Change Sets. An outbound change set is a set of changes you want to send from the currently logged in environment to another environment. E.g. Sandbox to Production. Click Continue if you see the “Understanding Deployments” page and then click “New.”

2.  Give it a name such as ‘BtsWebServiceDeployment’ and click Save to go to the Change Set page for BtsWebServiceDeployment.

3.  Under Change Set Components click Add.


4.  In the Component Type drop down select Apex Class, select both of the classes that were created and click “Add To Change Set.”


5.  Back on the properties page for the Change Set, click on Upload.

6.  Select Production and click Upload.


If all goes well, a message will let us know the change set was uploaded successfully. At this point we need to go to the Production environment and deploy the change set.

7.  In the production environment go to Setup and navigate to App Setup –> Deploy –> Inbound Change Sets. The new change set will be listed under Change Sets Awaiting Deployment.

8.  Click the change set name and then click Deploy. Validate can be done before this, but we are going to assume it will work. If so you will should see the deployment with a status of succeeded.

With that our SFDC environment now has a web service that BizTalk can call.


Export the WSDL and Generate Security Token

This is the last part to perform in SFDC. In this step the WSDL will be to exported from SFDC. That WSDL will then be used with the WCF Wizard in BizTalk to create our connections.

1.  In the SFDC production environment navigate to App Setup –> Develop –> Apex Classes.

2.  Under the Action column, right-click on WSDL and choose Save As next to the BizTalk Web Service that was deployed to production.


3.  Save the file with a .wsdl extension. Remember where this file is. It will be imported into BizTalk.

4.  Next generate the security token. SFDC requires a login to occur followed by subsequent requests. The security token along with the username and password is necessary to login to the SFDC. Go to Personal Setup –> My Personal Information –> Reset My Security Token.

5.  Click “Reset Security Token.” A security token will be email to the account associated with this SFDC account.


BizTalk Configuration

This will be posted as a follow up in a week or so.

Once you have created the web service in SFDC, BizTalk, or any client can go ahead and consume the web service. There is one additional step to this. When accessing SFDC web service, you need to first call a login web service to get a token that can be used in subsequent requests. Seroter’s blog comes in handy with a method he wrote that can be called from an orchestration which will go out and call the web service and store the token for later usage.



Still on BizTalk 2006? It’s time to upgrade

Very informative post on the reasons to upgrade off of BizTalk Server 2006 & R2. Apart from some nice features added since 2006 released the main issue is support as Microsoft’s mainstream support for 2006 will end in July this year.  It also gets unpleasant if you don’t have software assurance for BizTalk 2006 as you’ll have purchase new licenses.


ISO 20022 releases a “for dummies”

The guys behind the new standard for financial messaging have released a free online resource called ISO 20022 for dummies.

It’s an interesting read not only does it given a overview of the new standard it highlights the challenges organizations face in migrating. Many organizations will rely on middleware to help avoid the cost associated with a full-scale migration. A middleware product like BizTalk Server enables them to still use older standards internally and transform messages to the required format. This eliminates the need to update systems, particularly legacy systems that might be slated for replacement or suffer from a “don’t touch it” mindset.

Given there are probably still firms using ISO 7775 internally (replaced by ISO 15022 in 1998) and financial firms are notoriously adverse to change (particularly in IT), the adoption of ISO 20022 is going to take a while. Many of my clients in the finance industry are still running IE6, an application that is considered by many to be one of the most insecure applications around.  Even Microsoft would like to see the back of it. Although there’s at least 2260 people that disagree.

BizTalk via the SWIFT Accelerator already supports SWIFT MT messages and with SWIFT adopting the ISO 20022 standard with MX, based on XML. BizTalk will be well placed to pickup the slack. BizTalk will enable organizations to offer support for the new standards externally whilst reducing the risks and costs associated with a complete migration. Inversely organizations quick to adopt the new standards will be able to offer backwards compatibility to their customers and partners by leveraging BizTalk Server.