Giter Club home page Giter Club logo

force.com-javascript-rest-toolkit's Introduction

Warning

This project is deprecated, use JSforce instead.

Force.com JavaScript REST Toolkit

This minimal toolkit allows JavaScript in web pages to call the Force.com REST API in a number of different ways.

Background

ForceTK provides a convenient, thin JavaScript abstraction of the Force.com REST API, making the API more accessible to JavaScript code running in Visualforce, in hybrid mobile apps, and elsewhere.

Due to the same origin policy, JavaScript running outside the Force.com Platform may not use XMLHttpRequest to directly invoke the REST API, so a minimal PHP proxy is provided.

Recent Updates

  • Visualforce Remote Objects are proxy objects that enable basic DML operations on sObjects directly from JavaScript. Behind the scenes, the Remote Objects controller handles sharing rules, field level security, and other data accessibility concerns. Pages that use Remote Objects are subject to all the standard Visualforce limits, but like JavaScript remoting, Remote Objects calls don’t count toward API request limits.

    Since Remote Objects are more secure than RemoteTK (which does not respect sharing rules, FLS etc since system-level access is proxied via the RemoteTK controller), and similarly do not consume API calls (the main motivation for RemoteTK), RemoteTK has been removed from the toolkit.

  • Since the Summer '13 release, the /services/data endpoint has been exposed on Visualforce hosts, so no proxy is now required for REST API calls in JavaScript served via Visualforce (although the proxy is still required for calls to /services/apexrest). forcetk.js has been updated to reflect this.

  • Inserting or updating blob data using the create or update functions (passing base64-encoded binary data in JSON) is limited by the REST API to 50 MB of text data or 37.5 MB of base64–encoded data. New functions, createBlob and updateBlob, allow creation and update of ContentVersion and Document records with binary ('blob') content with a size of up to 500 MB. Here is a minimal sample that shows how to upload a file to Chatter Files:

      <apex:page docType="html-5.0" title="File Uploader">
        <h3>
          Select a file to upload as a new Chatter File.
        </h3>
        <input type="file" id="file" onchange="upload()"/>
        <p id="message"></p>
        <script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
        <script src="{!$Resource.forcetk}"></script>
        <script>
          var client = new forcetk.Client();
    
          client.setSessionToken('{!$Api.Session_ID}');
    
          function upload() {
              var file = $("#file")[0].files[0];
              client.createBlob('ContentVersion', {
                  Origin: 'H', // 'H' for Chatter File, 'C' for Content Document
                  PathOnClient: file.name
              }, file.name, 'VersionData', file, function(response){
                  console.log(response);
                  $("#message").html("Chatter File created: <a target=\"_blank\" href=\"/" + response.id + "\">Take a look!</a>");
              }, function(request, status, response){
                  $("#message").html("Error: " + status);
              });
          }
        </script>
      </apex:page>
    

    Under the covers, createBlob sends a multipart message. See the REST API doc page Insert or Update Blob Data for more details.

Dependencies

The toolkit uses jQuery. It has been tested on jQuery 1.4.4 and 1.5.2, but other versions may also work.

Configuration

ForceTK requires that you add the correct REST endpoint hostname for your instance (i.e. https://na1.salesforce.com/ or similar) as a remote site in Your Name > Administration Setup > Security Controls > Remote Site Settings.

Using ForceTK in a Visualforce page

Create a zip file containing app.js, forcetk.js, jquery.js, and any other static resources your project may need. Upload the zip via Your Name > App Setup > Develop > Static Resources.

Your Visualforce page will need to include jQuery and the toolkit, then create a client object, passing a session ID to the constructor. An absolutely minimal sample is:

<apex:page>
    <apex:includeScript value="{!URLFOR($Resource.static, 'jquery.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.static, 'forcetk.js')}"  />
    <script type="text/javascript">
		// Get an instance of the REST API client and set the session ID
		var client = new forcetk.Client();
		client.setSessionToken('{!$Api.Session_ID}');
    
        client.query("SELECT Name FROM Account LIMIT 1", function(response){
            $('#accountname').text(response.records[0].Name);
        });
    </script>
    <p>The first account I see is <span id="accountname"></span>.</p>
</apex:page>

More fully featured samples are provided in example.page and mobile.page. Watch a brief demo of the samples.

Using the Toolkit in an HTML page outside the Force.com platform

You will need to deploy proxy.php to your server, configuring CORS support (see comments in proxy.php) if your JavaScript is to be hosted on a different server.

Your HTML page will need to include jQuery and the toolkit, then create a client object, passing a session ID to the constructor. An absolutely minimal sample using OAuth to obtain a session ID is:

<html>
  <head>

	<!-- 
	jQuery - http://docs.jquery.com/Downloading_jQuery
	-->
    <script type="text/javascript" src="static/jquery.js"></script>
	<!--
	From jQuery-swip - http://code.google.com/p/jquery-swip/source/browse/trunk/jquery.popupWindow.js 
	-->
	<script type="text/javascript" src="static/jquery.popup.js"></script>
    <script type="text/javascript" src="forcetk.js"></script>
    <script type="text/javascript">
		// OAuth Configuration
		var loginUrl    = 'https://login.salesforce.com/';
		var clientId    = 'YOUR_CLIENT_ID';
		var redirectUri = 'PATH_TO_YOUR_APP/oauthcallback.html';
		var proxyUrl    = 'PATH_TO_YOUR_APP/proxy.php?mode=native';

		var client = new forcetk.Client(clientId, loginUrl, proxyUrl);

		$(document).ready(function() {
			$('#message').popupWindow({ 
				windowURL: getAuthorizeUrl(loginUrl, clientId, redirectUri),
				windowName: 'Connect',
				centerBrowser: 1,
				height:524, 
				width:675
			});
		});

		function getAuthorizeUrl(loginUrl, clientId, redirectUri){
		    return loginUrl+'services/oauth2/authorize?display=popup'
		        +'&response_type=token&client_id='+escape(clientId)
		        +'&redirect_uri='+escape(redirectUri);
		}
	
		function sessionCallback(oauthResponse) {
		    if (typeof oauthResponse === 'undefined'
		        || typeof oauthResponse['access_token'] === 'undefined') {
		        $('#message').text('Error - unauthorized!');
		    } else {
		        client.setSessionToken(oauthResponse.access_token, null,
		            oauthResponse.instance_url);

			        client.query("SELECT Name FROM Account LIMIT 1", 
			          function(response){
			            $('#message').text('The first account I see is '
			              +response.records[0].Name);
			        });
		    }
		}
    </script>
    <p id="message">Click here.</p>
</html>

More fully featured samples are provided in example.html and mobile.html.

Using the Toolkit in a Cordova app

Your HTML page will need to include jQuery, the toolkit and Cordova. You will also need to install the InAppBrowser plugin to be able to pop up a browser window for authentication. Create a client object, passing a session ID to the constructor. You can use https://login.salesforce.com/services/oauth2/success as the redirect URI and catch the page load in InAppBrowser.

An absolutely minimal sample using OAuth to obtain a session ID is:

<!DOCTYPE html>
<html>
  <head>
    <title>ForceTK Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
    <script type="text/javascript" src="js/jquery-1.11.2.min.js"></script>
    <script type="text/javascript" src="js/forcetk.js"></script>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript">
		// OAuth Configuration
		var loginUrl    = 'https://login.salesforce.com/';
		var clientId    = '3MVG9Km_cBLhsuPzTtcGHsZpj9HSp.uUwbHupEXhWi6k3JJphEv8swpsUYIFCZSLp8pi7YYMbRjeQUxptYdIt';
		var redirectUri = 'https://login.salesforce.com/services/oauth2/success';

		var client = new forcetk.Client(clientId, loginUrl);

        // Make our own startsWith utility fn
        if (!String.prototype.startsWith) {
          String.prototype.startsWith = function(searchString, position) {
            position = position || 0;
            return this.lastIndexOf(searchString, position) === position;
          };
        }

		document.addEventListener("deviceready", function(){
            $('#login').click(function(e) {
                e.preventDefault();
                var ref = window.open(getAuthorizeUrl(loginUrl, clientId, redirectUri), 
                					  '_blank', 'location=no,toolbar=no');
                ref.addEventListener('loadstop', function(evt) {
                    if (evt.url.startsWith(redirectUri)) {
                        ref.close();
                        sessionCallback(unescape(evt.url));
                    }
                });
            });
		});

		function getAuthorizeUrl(loginUrl, clientId, redirectUri){
		    return loginUrl+'services/oauth2/authorize?display=touch'
		        +'&response_type=token&client_id='+escape(clientId)
		        +'&redirect_uri='+escape(redirectUri);
		}
	
        function sessionCallback(loc) {
            var oauthResponse = {};
            
            var fragment = loc.split("#")[1];
            
            if (fragment) {
                var nvps = fragment.split('&');
                for (var nvp in nvps) {
                    var parts = nvps[nvp].split('=');
                    oauthResponse[parts[0]] = unescape(parts[1]);
                }
            }
            
            if (typeof oauthResponse === 'undefined'
                || typeof oauthResponse['access_token'] === 'undefined') {
			    alert("Unauthorized: No OAuth response");
            } else {
                client.setSessionToken(oauthResponse.access_token, null,
			    	oauthResponse.instance_url);
                
				client.query("SELECT Name FROM Account LIMIT 1", 
					function(response){
					    $('#message').text('The first account I see is '
						+response.records[0].Name);
				    }
				);
            }
        }
    </script>
  <head>
  <body>
    <button id="login">Click here to login</button>
    <p id="message"></p>
  </body>
</html>

A fully featured sample (including persistence of the OAuth refresh token to the iOS Keychain) for iOS is provided in cordova-ios.html. The sample uses Cordova 4.3.0 and the InAppBrowser and iOS Keychain plugins. Install these with

cordova plugin add org.apache.cordova.inappbrowser
cordova plugin add com.shazron.cordova.plugin.keychainutil

force.com-javascript-rest-toolkit's People

Contributors

chexxor avatar cwarden avatar hdramos avatar mr-menno avatar nkjm avatar paulroth3d avatar pomu0325 avatar pozil avatar rajaraodv avatar seanpat09 avatar shedal avatar svc-scm avatar tomgersic avatar vnehess avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

force.com-javascript-rest-toolkit's Issues

"Parameter is Incorrect" when uploading document from IE

Uploading documents with Chrome or Microsoft Edge works fine. But we get the following error when uploading from IE 11. Not sure if this is the issue, but debug shows the blob type as "multipart/form-data; boundary="boundary_84b4d2e704f267cc0a21cb089a4df950"" in IE. It shows it as "multipart/form-data; boundary="boundary_809c7d21418680febd458c08f6489116"" in Chrome.

image

Chatter REST API

Hey metadaddy -

I'm curious if your planning to drop some methods for doing the Chatter REST API calls into the toolkit?

It strikes me that it's only a matter of adding some URI building logic - I don't know if this in the pipeline or you have even thought about it?

Otherwise great work, really fast, functional JS!

Jordan

`client.ajax` does not work from within command buttons.

There is a failure in client.ajax when called from a command button, but not when called directly or from an anchor.

<apex:page >
    <script src="//code.jquery.com/jquery-1.5.2.min.js"></script>
    <apex:includeScript value="{!$Resource.forcetk_js}"/>
    <script type="text/javascript">
        var reportId = '00Oo00000037Vzx'; // set to report on your system
        var client = new forcetk.Client();
        client.setSessionToken('{!$Api.Session_ID}');
        var path = 'v31.0/analytics/reports/' + reportId + '?includeDetails=true';
        function success(){ console.log('hooray'); }
        function failure(){ console.log('ohnoes'); }
        function go(){ client.ajax(path, success, failure); }
        go(); // hooray
    </script>
    <a onclick="go()" href="#">click anchor</a> // hooray
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockSection columns="1" >
                <apex:pageBlockSectionItem >
                    <apex:commandButton value="click command button" onclick="go()"/> // ohnoes
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Usage in Lightning

Hi,
I was wondering how to use forcetk in Lightning.

I have a lightning component, where I've added forcetk and jQuery:
<ltng:require scripts="{!join(',',$Resource.forcetk,$Resource.jQueryMin_2_2_4)}" />

However, when I want to create the client in component's controller/helper, the following is not working:
var client = new forcetk.Client();

Do you have any ideas, what I might be doing wrong?

Force.com REST API batchSize

Hey guys,

I was running some SOQL queries and noticed that even though I set a limit of 1000 it still returns records at a max of 250 at a time. I'm not aware of anything from the org side that is setting this, so was looking at the REST API Developer Guide and found the Query Option Header.

I've added this into the Client.ajax beforeSend:
xhr.setRequestHeader('Sforce-Query-Options', 'batchSize=1000');
but it doesn't seem to affect the returned records batch size at all.

Any ideas?

401 requests still has mis-typed variable and missing variable

https://github.com/developerforce/Force.com-JavaScript-REST-Toolkit/blob/master/forcetk.js#L273

forcetk.Client.prototype.blob = function(path, fields, filename, payloadField, payload, callback, error, retry) {

https://github.com/developerforce/Force.com-JavaScript-REST-Toolkit/blob/master/forcetk.js#L315

that.blob(path, fields, filename, file, callback, error, true);

When a 401 occurs, it throws because file doesn't exist. If file happens to exist in another scope, then it passes the callback to the server (as data). Even worse, because true is passed as the error variable, it can continue infinitely because retry will always be undefined.

This kind of issue CANNOT occur if builds are being linted before distribution.

Fix examples

example.html throws

GET file:///home/kyrylo/code/Force.com-JavaScript-REST-Toolkit/static/jquery-ui.css  example.html:39
GET file:///home/kyrylo/code/Force.com-JavaScript-REST-Toolkit/static/jquery.js  example.html:44
GET file:///home/kyrylo/code/Force.com-JavaScript-REST-Toolkit/static/jquery.popup.js  example.html:48
GET file:///home/kyrylo/code/Force.com-JavaScript-REST-Toolkit/static/jquery-ui.js  example.html:52
GET file:///home/kyrylo/code/Force.com-JavaScript-REST-Toolkit/static/template.js  example.html:56
Uncaught ReferenceError: $ is not defined forcetk.js:45
Uncaught TypeError: undefined is not a function example.html:73

mobile.html throws

GET file:///home/kyrylo/Dropbox/code/Force.com-JavaScript-REST-Toolkit/static/jquery.popup.js  mobile.html:43
Uncaught TypeError: Object [object Object] has no method 'popupWindow' mobile.html:64

Office docs corrupt on download from SF UI after loading with forcetk.js with VF sample

I'm using the sample listed on the repo to load files from a vf page with forcetk.js as a static resource.
Text files, gif, pdf, office docs all load from the vf page successfully.
However after I download office docs from the SFDC UI and try to open them they are corrupted.
The same files uploaded by the SFDC UI then downloaded open correctly
Text, gifs, pdfs open fine.

ApexRest -- No 'Access-Control-Allow-Origin' header is present code 401

We have multiple orgs using ForceTK to call ApexRest services from VisualForce pages. Everything has been working just fine until last night. Now none of our calls are going through:

XMLHttpRequest cannot load https://cs41.salesforce.com/services/apexrest/v1/productmarkets/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://c.cs41.visual.force.com' is therefore not allowed access. The response had HTTP status code 401.

We've added the CORS records to the org with no difference in outcome. I understand that this is more than likely not a ForceTK issue, but something that has changed on the Salesforce side. I'm wondering if anyone might have suggestions on things I can try to get this to work?

POST requeswts not working

Hi Admin,

Thanks for the repo, it helped me greatly.

I am facing an issue with POST requests such as Create, Update and Delete. They are not working by GET requests are working perfectly. Can you please shed some light on this?
post issue

createBlob() fails in Firefox

When using Chrome or Safari, the Accept header is set to / (by the browser?), and all is good.
In Firefox (38.0.1), however, the Accept header is:
text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
and the API return SOAP instead of JSON. Which in turn causes JSON.parse() to fail with
JSON.parse: unexpected character at line 1 column 1 of the JSON data

A quick fix was to force the request header in forcetk.js blob():
request.setRequestHeader('Accept', '/');

503 error on Community page

Implementing the file upload functionality I noticed that when the Visualforce page is in a community I get a 503 error:

POST https://community-url.cs17.force.com/services/data/v33.0/sobjects/ContentVersion/ 503 (Service Unavailable)

forcetk.Client.blob @ forcetk:325
forcetk.Client.createBlob @ forcetk:346
upload @ UploadAttachment?pid=003g000000b0uIZAAY:153
onclick @ UploadAttachment?pid=003g000000b0uIZAAY:225

Any workaround or fix?

Error with Internet Explorer 11 - IE11 - "The parameter is incorrect"

Hi,
first amazing work with your Force.com - rest ToolKit !!!! , it works perfectly with all browser except Internet Explorer 11 (Actually I don't know with the previous versions).

I am using forcetk.Client.prototype.createBlob() and I will get an error in the "request.send(blob);" line , the error is "The paramater is incorrect".

Somebody could have the same issue? and some solution?

SalesforceProxy-Endpoint not defined in header

I must be missing something simple.
I've implemented the bulk.page example in a sandbox without any modifications but I am getting a 400 response with the error "SalesforceProxy-Endpoint not defined in header" when attempting to create the job.
Any thoughts on what I forgot to do? Thanks!

Client Secret?

I am trying to adapt your code to work with my REST API, and I am stuck at getting the refresh token. According to this page https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Obtaining_an_Access_Token_in_a_Web_Application_.28Web_Server_Flow.29 after getting the access token I need to do a grant_type=authorization_code to get the refresh token and I need to pass in the client_secret, but I don't see anywhere in your code that you are using this. Can you help me understand what you are doing differently?

Thanks

forcetk.Client.prototype.ajax not working .

I have created a hybrid salesforce app through forceios and I'm able to show all contacts.

But now I want show the Reports so I used REST API, but the method

forcetk.Client.prototype.ajax

is not getting called and there was no error shown in xcode or browser.

I have shared the code with you, Kindly help me out...

function callback(result){

alert("results");

}

function getReports(){

var path = '/v29.0/analytics/reports/00OD0000001ZbP7MAK/instances';

var method = 'POST';

var error = null;

var payload = null;

var retry = null;


alert("1");

forcetk.Client.prototype.ajax = function(path, callback, error, method, payload, retry) {

    alert("2");

    var that = this;

    var url = this.instanceUrl + '/services/data/v29.0/analytics/reports/00OD0000001ZbP7MAK/instances';

    alert(url);

    return $j.ajax({
                   type: method || "GET",
                   async: this.asyncAjax,
                   url: (this.proxyUrl !== null) ? this.proxyUrl: url,
                   contentType: method == "DELETE"  ? null : 'application/json',
                   cache: false,
                   processData: false,
                   data: payload,
                   success: callback,
                   error: (!this.refreshToken || retry ) ? error : function(jqXHR, textStatus, errorThrown) {

                   alert("error");

                   if (jqXHR.status === 401) {


                   that.refreshAccessToken(function(oauthResponse) {
                                           that.setSessionToken(oauthResponse.access_token, null,
                                                                oauthResponse.instance_url);
                                           that.ajax(path, callback, error, method, payload, true);
                                           },
                                           error);
                   } else {
                   error(jqXHR, textStatus, errorThrown);
                   }
                   },
                   dataType: "json",
                   beforeSend: function(xhr) {
                   if (that.proxyUrl !== null) {
                   xhr.setRequestHeader('SalesforceProxy-Endpoint', url);
                   }
                   xhr.setRequestHeader(that.authzHeader, "OAuth " + that.sessionId);
                   xhr.setRequestHeader('X-User-Agent', 'salesforce-toolkit-rest-javascript/' + that.apiVersion);
                   }
                   });
}

} //End of getReports

Proxy for apexrest

Hi @metadaddy , Do we have an example anywhere on how to make proxy call for apexrest service?. From the documentation we need proxy for apexrest , but I have my app in mobilesdk where I don't have any source URL nor my page is hosted in visualforce page. Please advise on how to call my apex class from force.com mobilesdk using forcetk plugin. Thanks in advance.

forcetk.Client.prototype.blob code has broken variable name

The signature for the function is

    forcetk.Client.prototype.blob = function(path, fields, filename, payloadField, payload, callback, error, retry) { 

But when the blob is called, the variable name is changed

                    } else if(request.status == 401 && !retry) {
                        that.refreshAccessToken(function(oauthResponse) {
                            that.setSessionToken(oauthResponse.access_token, null,oauthResponse.instance_url);
                            that.blob(path, fields, fileName, file, callback, error, true);
                        },
                        error);
                    } else {

A quick search of the file shows that fileName does not occur anywhere else in the file (and my linter agrees).

Add Cache-Control headers to requests in ForceTK

As of iOS 5, HTTP responses received within a web view would be cached only in memory, and not in the filesystem. However, in iOS 6, response data is cached in the filesystem in plain text, at this location - '[Application]/Library/Cache/[application name]/Cache.db'. In order to prevent sensitive data from being cached, it would be a good idea to add this line to all outgoing requests that go through ForceTK.

xhr.setRequestHeader('Cache-Control', 'no-cache, no-store');

within the ajax call in

forcetk.Client.prototype.ajax = function(path, callback, error, method, payload, retry) {}

Need upsert

upsert is not yet implemented, though it looks like there is a workaround - pass "externalField__c/value" as the object ID in an update call.

[enhancement] Add missing bower.json.

Hey, maintainer(s) of developerforce/Force.com-JavaScript-REST-Toolkit!

We at VersionEye are working hard to keep up the quality of the bower's registry.

We just finished our initial analysis of the quality of the Bower.io registry:

7530 - registered packages, 224 of them doesnt exists anymore;

We analysed 7306 existing packages and 1070 of them don't have bower.json on the master branch ( that's where a Bower client pulls a data ).

Sadly, your library developerforce/Force.com-JavaScript-REST-Toolkit is one of them.

Can you spare 15 minutes to help us to make Bower better?

Just add a new file bower.json and change attributes.

{
  "name": "developerforce/Force.com-JavaScript-REST-Toolkit",
  "version": "1.0.0",
  "main": "path/to/main.css",
  "description": "please add it",
  "license": "Eclipse",
  "ignore": [
    ".jshintrc",
    "**/*.txt"
  ],
  "dependencies": {
    "<dependency_name>": "<semantic_version>",
    "<dependency_name>": "<Local_folder>",
    "<dependency_name>": "<package>"
  },
  "devDependencies": {
    "<test-framework-name>": "<version>"
  }
}

Read more about bower.json on the official spefication and nodejs semver library has great examples of proper versioning.

NB! Please validate your bower.json with jsonlint before commiting your updates.

Thank you!

Timo,
twitter: @versioneye
email: [email protected]
VersionEye - no more legacy software!

Can't handle redirects.

I am using the forcetk proxy so that I can send AJAX requests and not have to worry about the cross domain restrictions.

The sequence is:

  1. I am on page in myapp.

    myapp.na9.visual.force.com/apex/OpportunityMap?id=a0AE0000007S5OyMAK

  2. I want to send ajax rest request to

    https://na9.salesforce.com/services/data/v20.0/query/?q=SELECT+Id,Name,FirstName,LastName+FROM+User+WHERE+Id+IN+BLAH+BLAH ...

But I can't. So I go thru the forcetk proxy which sends request to:

myapp.na9.visual.force.com/services/proxy?_=1366822377588

with the header:

Saleforce endpoing: na9.salesforce.com/services/data/v20.0/query/?q=SELECT+Id,Name,FirstName,LastName+FROM+User+WHERE+Id+IN+BLAH+BLAH ...

All super. However, if the session has timed out a 302 is returned. I see this in fiddler. The location header is back to salesforce page.

Location: https://na9.salesforce.com/visualforce/s...

This is fair enough. Salesforce is trying to redirect you to the login page because your login has timed out.

However, this HTTP response is never returned to the actual page. It looks like both IE and firefox detect that this is a cross domain restriction threat. Why? Because the original page that made the ajax request is in a different domain. This is fair enough. Why should a browser let a redirected ajax request go to another domain? This is a violation of cross domain restrictions.

Now, forcetk makes cross domain requests possible for ajax requests in the first place. But it does not seem to be able to handle redirects that go to the same domain the service endpoint is actually on. I am wondering is there any way it could be expanded or if there is anything I could do to be able to get around this?

Currently, if you are using forcetk you can't really deal with with AJAX requests when your session times out.

Aura Error: Unsupported MIME type

Details: I am trying to create a Content-Version record and the file type is xlsx. I am passing blob and type is application/octet-stream which is whitelisted. And I am using in lightning component v40.0 where locker service is enabled.
Issue: Error message Unsupported MIME type on line 282(used forcetk.js file).

Phonegap + Windows 8: X-Frame-options

I have OAuth set up for portal users as shown here:

https://developer.salesforce.com/blogs/developer-relations/2013/02/oauth-for-portal-users.html

App works fine in iOS and Android but in Windows 8 I get this error:

APPHOST9613: The app couldn’t navigate to [url] because of this error: 401.

I tried using an iframe with the same url and I get the same error.

Some research suggest that this problem is related to X-Frame-options.

@metadaddy-sfdc

This is a sample response headers:

Cache-Control:no-cache, must-revalidate, max-age=0, no-store, private,s-maxage=0
Content-Type:text/html;charset=UTF-8
Date:Fri, 31 Oct 2014 17:34:30 GMT
org.eclipse.jetty.server.include.X-FRAME-OPTIONS:SAMEORIGIN
org.eclipse.jetty.server.include.X-XSS-Protection:0
P3P:CP="CUR OTR STA"
Pragma:no-cache

Transfer-Encoding:chunked
X-Powered-By:Salesforce.com ApexPages

Another theory is that the problem is cause because the redirect returns 401 as the error message show.

https://site.force.com/setup/secur/RemoteAccessAuthorizationPage.apexp

salesforce proxy url is not correct if the browser url is formed differently by sso

Salesforce proxy url is looking at element[0] or element[1] of url split by dot in order to get domain. which is not always correct. I think domain should be obtained from {!$Api.Enterprise_Server_URL_410} to make sure it is always correct and it need to be always passed. I think fixing comments will help users or we should use salesforcebase url

/**
     * Set a session token and the associated metadata in the client.
     * @param sessionId a salesforce.com session ID. In a Visualforce page,
     *                   use '{!$Api.sessionId}' to obtain a session ID.
     * @param [apiVersion="v29.0"] Force.com API version
     * @param [instanceUrl] Omit this if running on Visualforce; otherwise 
     *                   use the value from the OAuth token.
     */
    forcetk.Client.prototype.setSessionToken = function(sessionId, apiVersion, instanceUrl) {

forcetk.Client constructor builds incorrect instanceUrl when running on na1.salesforce.com

Current code fails to take into account VF hosts such as na1.salesforce.com:

    // location.hostname is of the form 'abc.na1.visual.force.com', so we
    // can simply split it on '.' and take the second element of the
    // resulting array
    this.instance_url = "https://" + location.hostname.split(".")[1]
    + ".salesforce.com";

As a result, it erroneously builds an instanceUrl such as salesforce.salesforce.com. Since there is no way to directly get the instance component or the whole URL in Visualforce, an acceptable heuristic would be to look at the number of elements in the hostname and choose the first or second as appropriate:

    // location.hostname can be of the form 'abc.na1.visual.force.com' or
    // 'na1.salesforce.com'. Split on '.', and take the [1] or [0] element
    // as appropriate
    var elements = location.hostname.split(".");
    var instance = (elements.length == 3) ? elements[0] : elements[1];
    this.instance_url = "https://"+instance+".salesforce.com";

Many thanks to @jeffdonthemic for the bug report!

Passing correctly typed fields causes INVALID_FIELD error

Setting, NumberOfEmployees to an integer value (rather than a string) when creating an Account results in an INVALID_FIELD error. Looks like changes to coerce string field values to correct type resulted in breakage when passing correct field type.

How to perform bulk DML operations in salesforce hybrid app ?

I have created a salesforce hybrid app using Forceios and I'm able to perform the CRUD operations using forcetk client instance .

Now I want to perform mass update on salesforce objects but I didn't find any running example code to do so.

For 2 days I have searched for topics like BULK API, SmartSync , JSForce but I don't understand how to implement them.

Kindly share a code to perform Bulk DML operations like mass update , mass delete through salesforce hybrid app.

Kindly Help me out ....

Add Chatter REST API calls

Here is code for forcetk.js that adds in the ability to access Chatter.

/*
 * Retrieves field values for a Chatter record of the given type.
 * @param objtype object type; e.g. "comments"
 * @param id the record's object ID
 * @param [fields=null] optional comma-separated list of fields for which
 *               to return values; e.g. Name,Industry,TickerSymbol
 * @param callback function to which response will be passed
 * @param [error=null] function to which jqXHR will be passed in case of error
 */

forcetk.Client.prototype.chatter = function(objtype, id, fieldlist, callback, error) {
if (!arguments[4]) {
    error = callback;
    callback = fieldlist;
    fieldlist = null;
}
var fields = fieldlist ? '?fields=' + fieldlist : '';
this.ajax('/' + this.apiVersion + '/chatter/' + objtype + '/' + id
          + fields, callback, error);
}

Need help connecting to org using phonegap example

As I'm trying at the moment, the forcetk constructor is being passed the consumer key as the clientid and I have the default callback url set (https://login.salesforce.com/services/oauth2/success) but I just can't seem to get a connection. I've also set https://na9.salesforce.com my instance as a remote site.

I've worked with the forcetk from inside the org through a vf page and it works awesome but I can't seem to get it going from outside. Any pointers I might have missed?

One extra character in file body after upload using the createBlob() function in forceTK.js

DESCRIPTION:
If we try to upload a new ContentVersion using the createBlob() function in forceTK.js, then an uploaded file will have one extra byte at the end of content body. It will be a "new line" character (LF).

As a result, some uploaded files get corrupted and cannot be recognized by programs if we download them again. For example, MS Excel and MS Word say that such files are incorrect and suggest to fix the issues in format.

SOLUTION:
The issue is in the blob() function (line #293). It adds "\n\n" sequence between payload and final boundary, but only one "\n" is needed.

Call Apex REST POST Method Error

returned this 'net::ERR_CONNECTION_RESET'

Here is my code:

 var url = '/services/apexrest/namespace/DownloadService/';
 tkClient.apexrest(
                url,
                function(response){
                    console.log(Base64.decode(response));
                    var responseJson = Base64.decode(response);
                },
                function(error){
                    console.log(error);
                },
                "POST",
                null,
                '{"jsonData":"eyJvYW1lAwMDAwWVNJbUFBTyJ9"}',
                false
            );

Need error handling

Currently, the toolkit ignores errors. Need to add a facility to pass an error callback to each API.

Uploading multiple content files to salesforce using ForceTK : UNABLE_TO_LOCK_ROW error

We have a code in method to which we are passing index and uploading a file to salesforce content one by one , once the response is received i.e ID is received , call is made again so same method with index change.
This process works fine for many instance however as there are large number of users , we are sometimes seeing error and instead of getting ID in response we are getting error :

0: {message: "unable to obtain exclusive access to this record", errorCode: "UNABLE_TO_LOCK_ROW",…}

  1. errorCode: "UNABLE_TO_LOCK_ROW"
  2. fields: []
  3. message: "unable to obtain exclusive access to this record"

We are getting this error if files are uploaded for same session. It is like session issue ? or there is some issue as we are uploading all files one by one and still there is error as unable to obtain exclusive access to this record.

Retrive method can not transfer attchment base64 string body correctly

I've got an issue to download attachment body in our app.
We use forcetk retrieve method and never got the body data but the uri(something like '/services/data/v33.0/sobjects/Attachment/00P25000000aiNREAY/Body').
Then I use the ajax method of forcetk client directly to call the resource 'services/data/v33.0/sobjects/Attachment/00P25000000aiNREAY/Body' and every time it results to error handling function. it seems that the responseText is right but when I use btoa(unescape(encodeURIComponent(XXX))) to convert the result into base64 string, the converted data is never matches correct .
Would you give me some advice here?

SOSL search string is incorrect in forcetk.sj

The code to execute a sosl search is incorrect in forcetk.js.

The original code is:

forcetk.Client.prototype.search = function(sosl, callback, error) {
this.ajax('/' + this.apiVersion + '/search?s=' + escape(sosl)
, callback, error);
}

it should be:

forcetk.Client.prototype.search = function(sosl, callback, error) {
this.ajax('/' + this.apiVersion + '/search?q=' + escape(sosl)
, callback, error);
}

The "?s" should be replace with "?q".

Problem with xlsx and docx

Hi,

You have a problem with this code:
var blob = new Blob([ "--boundary_" + boundary + '\n' + "Content-Disposition: form-data; name=\"entity_content\";" + "\n" + "Content-Type: application/json" + "\n\n" + JSON.stringify(fields) + "\n\n" + "--boundary_" + boundary + "\n" + "Content-Type: application/octet-stream" + "\n" + "Content-Disposition: form-data; name=\"" + payloadField + "\"; filename=\"" + filename + "\"\n\n", payload, "\n\n" + "--boundary_" + boundary + "--" ], {type : 'multipart/form-data; boundary=\"boundary_' + boundary + '\"'});

It should be:
var blob = new Blob([ "--boundary_" + boundary + '\n' + "Content-Disposition: form-data; name=\"entity_content\";" + "\n" + "Content-Type: application/json" + "\n\n" + JSON.stringify(fields) + "\n\n" + "--boundary_" + boundary + "\n" + "Content-Type: application/octet-stream" + "\n" + "Content-Disposition: form-data; name=\"" + payloadField + "\"; filename=\"" + filename + "\"\n\n", payload, "\n" + "--boundary_" + boundary + "--" ], {type : 'multipart/form-data; boundary=\"boundary_' + boundary + '\"'});

The extra line corrupts the xlsx and docx files.

Thanks,
Yishay

IE11 browser Issue: Facing issue with Forcetk.js(Rest toolkit), Parameter is incorrect

Hi,

I am using IE11 browser. I am using Forcetk.js to for file upload into content version. The script is working fine in Mozilla and Chrome.

But in IE11, I get the below error in Forcetk.js file. Please help if any one faced similar issue.

forcetk js error

I have posted the same issue here:
http://salesforce.stackexchange.com/questions/111774/ie11-browser-issue-facing-issue-with-forcetk-jsrest-toolkit-parameter-is-inc?noredirect=1#comment154859_111774

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.