Simon Fell > Its just code > PocketSOAP and SForce

Sunday, May 9, 2004

This tutorial shows how to use PocketSOAP to access SForce, the Web Services API.

  • First off, if you don't have a account, head over to and sign up for the free developers edition account
  • Next, make sure you've got PocketSOAP and the PocketSOAP WSDL Wizard (v2.3 or greater) installed.
  • Now we need to grab the WSDL for your account, login to, click the setup link at the top right, then from the left menu under studio select WSDL Generator. Finally, right click on the Download Enterprise WSDL link and select save link to disk, and save the WSDL somewhere on your machine.
  • Now we can run it through the WSDL Wizard to get an easy to use object model generated for us. Start the WSDL Wizard, enter the path and filename of the WSDL in the top box, and the second line select a directory for it to generate the VB6 files to, and enter sforce as the name of the project in the bottom box.
  • Hit next, you'll be presented with the list of bindings, of which there's only one, so hit next again, now you can see the list of methods, leave them all selected and hit next again. The Wizard will now generate the code, then say its finished. Click OK to close the wizard.
  • If everything went according to plan, you now have a ton of generated VB code (~200 classes!), open the sforce.vbp project and compile it.
  • Now start a new VB standard EXE project, and do add reference, scroll down the list and pick "SForce Proxy class....". The main entry point into the generated proxy code is the Soap class (this is named from the WSDL), if you look at this in the object browser, you'll see a bunch of methods, one for each one listed in the WSDL.

Now, in order to access the data we need to login, so drop a button on your form, and add this code

    ' create the proxy object and the login message
    Dim svc As New Soap
    Dim lr As loginResponse
    Dim lo As New login
    lo.Username = "<your login>"
    lo.password = "<your password>"
    ' login
    Set lr = svc.login(lo)

SForce uses a document/literal style service, so the programming model exposed by the generated proxy has a method for each operation in the WSDL where each method takes an object that represents the request message, and returns an object that represents the response message. In addition any SOAP headers that may apply to the operation are also passed as parameters to the method (this is likely different to the programming model generated by other tools, I'll save why I think this is better for another day)

Now, going back to our login code, you can see that we create an instance of the login message, populate its data (username & password in this case), and call the login method, this returns a loginResponse message.

The loginResponse message contains a single loginResult stucture that contains a few pieces of useful information, the 2 important ones are the serverUrl and the sessionId. In the SForce world, once you're authenticated you communicate with a different server (as indicated by the serverUrl value), and you tell it your authentication info by passing the sessionId back to the server in a SOAP Header. So what we'll do next is create the SOAP header object, and populate it with the sessionId, and point the proxy object at the new Url.

    ' create the session header, and update the server Url that we connect to
    Dim sh As New SessionHeader
    sh.sessionId = lr.result.sessionId
    svc.Url = lr.result.serverUrl

Now, we'll create a couple of new Accounts, we do this via the create operation, here's how the object browser shows the create method.

The create_ parameter is the create message, and there's 2 headers we can send, the SessionHeader which we've already discussed and the SaveOptions header, this header lets use control how lead assignment is handled, which we don't care about for Accounts, so we can just pass nothing for that in this case.

The create message contains an array of sObjects, everything in is based on an sObject, the Account object inherits (or extends in XSD speak) from sObject. So, we need to create an array of sObjects, where each item in the array is an account. One wrinkle is that VB won't let you pass a statically sized array to a property call, so you need to ensure that your array is dynamically sized (i.e. use redim)

    ' create 2 new accounts, note that the create call uses an object hierarchy    
    ' but in VB we need to pass sObject() to the create call, so declare the array
    ' as that, but populate it with account objects
    Dim acc() As sObject
    ReDim acc(1)
    Dim na As New Account
    na.Name = "Simon's Test Account"
    na.AccountNumber = "42424242"
    na.AnnualRevenue = 10000
    Set acc(0) = na
    Set na = New Account
    na.Name = "Simon's other test account"
    na.AccountNumber = "24242424"
    na.AnnualRevenue = 11111
    Set acc(1) = na

Now we've got the 2 accounts we want to create, we can create the Create message, and make the call to the create operation.

    ' do the create call
    Dim cr As New Create
    cr.sObjects = acc
    Dim cres As createResponse
    Set cres = svc.Create(cr, sh, Nothing)

All that's left is to check the response, to see if there are any errors (as there might be an error with only a single object, there's a separate error indication for each Account we tried to create).

    ' check the results
    Dim idx As Long
    For idx = LBound(cres.result) To UBound(cres.result)
        If Not cres.result()(idx).success Then
            debug.print "failed creating account: " & cres.result()(idx).errors()(0).message
            debug.print "created account with Id " + cres.result()(idx).id
        End If

That's it!, you can now login through the web interface and see the new accounts you've created, the rest of the functions all work in the same manner, finally the describeSObject call exposes a lot of information about the fields on each of the sObjects derived types in the system (including any custom fields or custom objects you may of created yourself through studio), making it easy to do grid views and similar that are completely driven by the meta data.