« Microsoft Dynamics AIF Error, missing class attribute | Main | BizTalk Integrations with Salesforce.com »
Wednesday
Jun012011

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].

image

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]

image

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>
[Serializable]
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
System.Diagnostics.EventLog.WriteEntry("Utilities",
"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);

System.Diagnostics.EventLog.WriteEntry("Utilities",
"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.

image

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.

image

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.

image

// 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) =
"<headers><SessionHeader><sessionId>"
+ sessionId
+"</sessionId></SessionHeader></headers>";

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\">
<ns0:accountName></ns0:accountName></ns0:GetAccountId>"
);
msgGetAcctId.parameters = xmlDoc;
msgGetAcctId.parameters.accountName = msgAddAcct.AccountName;
msgGetAcctId(WCF.Headers) =
"<headers><SessionHeader><sessionId>"
+ sessionId
+"</sessionId></SessionHeader></headers>";
image

 

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">
<GlobalId>Bts1101</GlobalId>
<AccountName>Synthesis Consulting, Inc</AccountName>
<LastName>Browning</LastName>
</ns0:AddContact>
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">
<ns0:globalId>Bts1101</ns0:globalId>
</ns0:GetContact>

Update a contact

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

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.

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>