Placeholder

Customer Forum

Updating API objects through ColdFusion

External Posted: 2011-02-08 09:27

I've been tasked with writing a connector that sits between your API and our own internal system, and so far everything's gone fine - I can pull down leads assigned to myself which is the main thing we need.
 
However next I've come to try and update one of these, but it's not working. I'm using Adobe ColdFusion which I appreciate yourselves don't use, but this extract is fairly self-explanatory:

(bear in mind at this point I've already logged in and established my Session ID, which I pass back as a cookie variable, this works fine for GETs)


<cfhttp method="PUT" url="https://secure.workbooks.com/crm/sales_leads.api" result="conn">
       <cfhttpparam type="cookie" name="Workbooks-Session" value="#AuthToken#" />
       <cfhttpparam type="formfield" name="__method[]" value="put" />
       <cfhttpparam type="formfield" name="_ff[]" value="id" />
       <cfhttpparam type="formfield" name="_ft[]" value="eq" />
       <cfhttpparam type="formfield" name="_fc[]" value="980" />
       <cfhttpparam type="formfield" name="id[]" value="980" />
       <cfhttpparam type="formfield" name="lock_version[]" value="8" />
       <cfhttpparam type="formfield" name="sales_lead_rating_type[]" value="warm" />
</cfhttp>


Which simply sends off a PUT request, and then attempts to update the Lead ID 980. I've tried all different combination of filters and fields from your documentation however all I get back is this:
 
Cannot update the object [#, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #] in the '' namespace if it is an Array


Can you give me any further info on why I can't update the object? What probably doesn't help is that I have absolutely no experience of using the product whatsoever...

Cheers
Owain

Workbooks Support Posted: Tue, 08.02.2011 - 11:14

Hi Owain,

At an initial glance I cannot see anything terribly wrong with your request apart from the value of the __method[] attribute should really be in uppercase.  Can you please run your code, and reply here with the following information:

* The username that your code is logging in as (but not your password - this is a public forum!)

* The database that your code is logging into if there is more than one in your account

* The approximate time of the failed request

I can then look at the server logs.  The error message that you are getting is not terribly enlightening; hopefully we can improve it.

Regards,

    Jonathan.

External Posted: Thu, 10.02.2011 - 11:03

Hi Jonathan

I'll send this over to you in an email if that's okay, rather than posting the aforementioned details up here.

With you shortly...

Workbooks Support Posted: Thu, 10.02.2011 - 11:28

Hi Owain,

    The logs show that the request is arriving without any parameters; not a single one.  I'm afraid I don't know ColdFusion, so I've no idea whether your code is correct or not.  Are there any tools for inspecting what you are sending?  If so I don't mind reviewing any logs you can get from your end to help you identify the issue.

Cheers,

    Jonathan.

External Posted: Thu, 10.02.2011 - 11:43

Hi Jonathan

Interesting, I tried changing this to use a POST rather than a PUT, as I've never needed to use PUTs with ColdFusion before, so can't really vouch for them working properly. First up, I got an error about my authenticity token being invalid; I'd been sending this as a cookie value (which works for gets). However changing that to be a posted formfield, and I get:

"We are sorry that there has been an error. Workbooks has recorded the incident with reference: 228238-5757-1675"

Can you get anything out of this incident ID that might give me a clue?

 

Cheers

Owain.

Workbooks Support Posted: Thu, 10.02.2011 - 12:05

OK, we are getting somewhere.

The incident ID refers to the '_authenticity_token' not being sent, because it was in a cookie rather than in a parameter.  It must be a parameter.

The POST worked (the parameters were included), but Workbooks interpreted it as a request to create rather than update Sales Leads.  This sort of behaviour can happen with client libraries that do not know that in HTTP parameters can be sent in the body of a request for a PUT as well as a POST.  We provide a workaround for this problem as follows:

  • Use POST to send the request, but crucially, include a special parameter called "_method" (NOTE: one underscore, not two) whose value is "PUT".  We usually use the HTTP verb to work out what the request is for, but if the _method parameter is provided, that overrides.
  • The "__method[]" (NOTE: two underscores and the square brackets) is an Array of verbs (uppercase) that specify what to do for each element in the matrix of parameters that you can send to update a batch of objects at the same time.  So, you can set __method[] to ['POST', 'PUT', 'DELETE'] along with an appropriate id[] Array and lock_version[] Array to create one object, modify another and delete a third, all in a single request.
  • Make sure that the verbs are in uppercase in both the _method and __method[] parameters.  (I have raised an issue to improve the service to accept the verbs in any case, which will be fixed in due course).

Hopefully that works.

Regards,

    Jonathan.

External Posted: Thu, 10.02.2011 - 12:19

Right, getting somewhere with a POST but it's not accepting my authenticity token no matter how I send it. What should it be called? For GETs I've been calling it "Workbooks-Session" and that's worked, but doesn't seem to here. Therefore, I'm sending it under both possible names, as cookie *and* formfield, but I'm still getting back:

Invalid _authenticity_token - has your session expired?

Request:

<cfhttp method="POST" charset="utf-8" url="https://secure.workbooks.com/crm/sales_leads.api" result="conn">
    <cfhttpparam type="formfield" name="_method" value="PUT" />
    <cfhttpparam type="cookie" name="Workbooks-Session" value="#AuthToken#" />
    <cfhttpparam type="formfield" name="Workbooks-Session" value="#AuthToken#" />
    <cfhttpparam type="cookie" name="_authenticity_token" value="#AuthToken#" />
    <cfhttpparam type="formfield" name="_authenticity_token" value="#AuthToken#" />
    <cfhttpparam type="formfield" name="_ff[]" value="id" />
    <cfhttpparam type="formfield" name="_ft[]" value="eq" />
    <cfhttpparam type="formfield" name="_fc[]" value="980" />
    <cfhttpparam type="formfield" name="id[]" value="980" />
    <cfhttpparam type="formfield" name="lock_version[]" value="8" />
    <cfhttpparam type="formfield" name="sales_lead_rating_type[]" value="warm" />
</cfhttp>

Workbooks Support Posted: Thu, 10.02.2011 - 12:40

Hi Owain,

We are receiving this:

Processing Crm::SalesLeadsController#update_many to api (for <IP_address_deleted> at 2011-02-10 12:16:53) [PUT]
Session ID: 8fc5cd36fcf8879b65d0506b16127144
Parameters: {"format"=>"api", "sales_lead_rating_type"=>["warm"], "Workbooks-Session"=>"8fc5cd36fcf8879b65d0506b16127144", "_ft"=>["eq"], "action"=>"update_many", "_method"=>"PUT", "lock_version"=>["8"], "id"=>["980"], "_fc"=>["980"], "controller"=>"crm/sales_leads", "_ff"=>["id"], "_authenticity_token"=>"8fc5cd36fcf8879b65d0506b16127144"}
 

The Session ID is being collected correctly from the cookie; there is no point in sending Workbooks-Session as a parameter.

The _authenticity_token should be a parameter - no point in sending it as a cookie - but notice that the value is the same as your Session ID.  You should have got a different value back in the login response.

Cheers,

    Jonathan.

External Posted: Thu, 10.02.2011 - 12:48

Woohoo!

I think I'd probably assumed the session id and auth token were the same thing, I hadn't had to use the token yet. Posting the request now works (well errors, but something to do with stale version of the object).

For posterity's sake:

<cfhttp method="POST" charset="utf-8" url="https://secure.workbooks.com/crm/sales_leads.api" result="conn">
    <cfhttpparam type="formfield" name="_method" value="PUT" />
    <cfhttpparam type="cookie" name="Workbooks-Session" value="#SessionID#" />
    <cfhttpparam type="formfield" name="_authenticity_token" value="#AuthToken#" />
    <cfhttpparam type="formfield" name="_ff[]" value="id" />
    <cfhttpparam type="formfield" name="_ft[]" value="eq" />
    <cfhttpparam type="formfield" name="_fc[]" value="980" />
    <cfhttpparam type="formfield" name="id[]" value="980" />
    <cfhttpparam type="formfield" name="lock_version[]" value="8" />
    <cfhttpparam type="formfield" name="sales_lead_rating_type[]" value="warm" />
</cfhttp>

Cheers muchly.

Workbooks Support Posted: Thu, 10.02.2011 - 12:54

Excellent news.

The message about the object being stale is due to the lock_version not being correct.  The lock_version is incremented on the object whenever it is changed.  This ensures that if your client gets a copy of the object, someone else updates the object and then you try to submit an update to the object, you don't overwrite the other person's changes.  In this case, the object's lock_version was 9, but you submitted 8, so it was updated earlier either by your code, or by someone else.

Cheers,

    Jonathan.

External Posted: Thu, 10.02.2011 - 13:15

Yup, I changed the version number and it updated bootifully.

Cheers muchly.