• YD98
  • -1 Points
  • Member since 2020

  • Chatter
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 0
  • 3
Hi all and Happy new year.

I had this task to create a custom Related list on the Account Page Layout with Visualforce and it all works fine. I've got all the records that i need and all the required fields and of course "New Project" button.

New Project button

However the only issue is that when i added the "New BD Project" button, when the new page is opened and the user change his mind and press "Cancel" it returns to the Visualforce page only, not to the Account Page Layout.


I tried different solution, but i could not make it work.
Here is the commandlink button
<div style="margin-left: 30%;">
<apex:commandLink value="New BD Project" action="       {!URLFOR($Action.BD_Project__c.New)}" target="_parent"     styleClass="btn" style="text-      decoration:none;padding:4px;"/>

I found the whole Visualforce page and Controller in another solution which was for Contact Related list and i modified it to fit my requirements. The only change is that in the working Contact solution(where when you press cancel it returns you to the previous page) is that the code for the New Object is in the Controler:
public pageReference newContact()
pageReference pageRef = new pageReference(URL.getSalesforceBaseUrl().toExternalForm() + '/003/e?&retURL=' + accounts.id);
return pageRef;

Did any of you guys had a similar issue and found a solution.

Kind regards,

Here is the controller and the Visualforce that i'm using.:

In Objective C, I follow the steps as outlined here and it works fine: https://developer.salesforce.com/docs/atlas.en-us.noversion.mobile_sdk.meta/mobile_sdk/ios_rest_apis_using_methods.htm?search_text=forceios

But when following the same steps translating the code into Swift, I run into an issue with the SFRestRequest initializer, whose signature is below:
Public convenience init(method: SFRestMethod, path: String, queryParams: [String : String]?)

As you can see, queryParams takes a Swift Dictionary with a key and value of the String type.  But when you follow the example, it seems you end up with a Dictionary with a key of the String type and value of the Dictionary type; and thus we have a type mismatch.

This doesn't seem to be a problem in Objective C, because upon inspection of the method signature in SFRestRequest.m, queryParams appears to be able to take a generic NSDictionary: 
+ (instancetype)requestWithMethod:(SFRestMethod)method path:(NSString *)path queryParams:(NSDictionary *)queryParams

For reference here is the Swift code I'm trying out:
//build the queryParams dictionary from a JSON String
let body: String = "{ \"body\" :{\"messageSegments\" :[{ \"type\" : \"Text\",\"text\" : \"My Comment\"}]}}"
        let queryParams = SFJsonUtils.objectFromJSONString(body) as! [String:AnyObject] 
//construct and send the request
        let request = SFRestRequest(method: SFRestMethod.POST, path: "/services/data/v36.0/connect/communities/my_community_ID/chatter/feed-elements/my_element_ID/capabilities/comments/items", queryParams: queryParams as? [String:String])
        SFRestAPI.sharedInstance().send(request, delegate: self)

But unwrapping queryParams fails and resolves to nil.  Trying to forcefully cast queryParams to [String:String] does not work either, and just causes a crash.

How might I get around this?

We are developing a mobile app using salesforce mobile sdk for android(and ios too) and phonegap. This requires downloading Salesforce Content(Content can be a file of any type/extension) directly and saving it into mobile device.

We tried below url which exposes the content of the Salesforce Content document.


Since the above url doesnt allow direct download of file, we are parsing the content and writing it into a file to save in mobile device.


//This function is invoked when download link is clicked and dwnldDocParams contains saleforce content record id and filename

function downloadFileToDevice(dwnldDocParams){                                

                var dwnldDocId = dwnldDocParams.substring(0,18);

                var fileNameWithExt = dwnldDocParams.substring(18);

                forcetkClient.getContentData(dwnldDocId, onSuccessContentData, onErrorSfContentData);



forcetk.Client.prototype.getContentData = function(recordId, callback, error) {

        var query = '/' + this.apiVersion + '/sobjects/ContentVersion/'+recordId+'/VersionData'

        this.ajaxForContent(query, callback, error);



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

        var that = this;

        var url = this.instanceUrl + '/services/data' + path;

                                //This is the sample url




            type: method || "GET",

            async: this.asyncAjax,

            url: (this.proxyUrl !== null) ? this.proxyUrl: url,


                                                contentType: 'application/octetstream', //since the response sent by salesforce has Content-type : application/octetstream for content of any type(text,image,docx..)


                                                cache: false,

            processData&colon; false,

            data&colon; payload,

            success: callback,

            error: (!this.refreshToken || retry ) ? error : function(jqXHR, textStatus, errorThrown) {

                if (jqXHR.status === 401) {

                    that.refreshAccessToken(function(oauthResponse) {

                        that.setSessionToken(oauthResponse.access_token, null,


                                                                                                that.ajaxForContent(path, callback, error, method, payload, true);



                } else {

                    error(jqXHR, textStatus, errorThrown);




                                                dataType: "text", //valid datatypes are text,json,xml,html,jsonp


            beforeSend: function(xhr) {

                if (that.proxyUrl !== null) {

                    xhr.setRequestHeader('SalesforceProxy-Endpoint', url);


                xhr.setRequestHeader(that.authzHeader, "Bearer " + that.sessionId);

                xhr.setRequestHeader('X-User-Agent', 'salesforce-toolkit-rest-javascript/' + that.apiVersion);


                if (that.userAgentString !== null) {







//Success callback function         

function onSuccessContentData(response) {

    var $j = jQuery.noConflict();

                //Phonegap method

    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,

                               function (fileSystem) {

                //fileSystem.root.getFile("readme.txt", {create: true, exclusive: false}, //here file name is hardcoded just for static verification for writing into files of different types

                fileSystem.root.getFile("testimage.png", {create: true, exclusive: false},

                //fileSystem.root.getFile("sampleDoc.docx", {create: true, exclusive: false},

                function (fileEntry) {


                                        function gotFileWriter(writer) {

                                                                                writer.onwrite = function(evt) {

                                                                                console.log("write success");



                                                    }, fail);

                                    }, fail);

                }, fail);



The above code works only for text files. For text files response is text only.For other files, we could observe Though we could get response for files of other types also and write into file in device, they could not be viewed. May be the response sent as octetstream need to processed in some way before writing into file. Dont know if there is any issue writing binary data into file using above phonegap function. Any pointers to successfully write content into file (of any type) is  really helpful.


Sample response obtained for an image(png) file:


07-18 15:11:10.822: D/CordovaLog(1421): >onSuccessContentData&colon;response--"?PNG\r\n\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0000 \u0000\u0000\u0000?\b\u0002\u0000\u0000\u0000\u0005?v?\u0000\u0000\u0000\u0019tEXtSoftware\u0000Adobe ImageReadyq?e<\u0000\u0000\u0000?IDATx???1\u0012?0\u0010\u0005Pp????\n?86\u0014R?\u0006?`?\u0001,?\u0005\u0016_.??o\"Yp?????.?\u0012\nt\u0000?z??D;?(?\u001e?/?M>?K\u0013??n???\t6???\t\u0016?\u0013?\u0003?\u0004{'???g??'pL?\"??\u001e?;?RJl?5?c,0MS??1??\u0001\u0000\u0000\u0000\u0000r\\??s?a\u0018r??\u000f\u0000\u0000\u0000\u0000\u0000 Kgw???E\u0000\u0000\u0000\u0000\u0000\u0000\u0000[4^??\"S?\u0007\u0000?E?A?$P\"\tN?,??\u0018?>@\u0002C?J$???#??\u0004??\u0004???3?4c????\u0001\u0000\u0000\u0000\u0000?\u0004\b\u001f?v?\u0003\u0000\u0000\u0000\u0000\u0000\u0000|?\u0007?B?\u0019?|??\u0000\u0000\u0000\u0000IEND?B`?"



It would be really great if there is any way to download the file directly from salesforce instead of reading response and writing manually into a file in device.

I could find another url which DIRECTLY DOWNLOADS THE FILE if we are currently in salesforce session. I tried this url in place of url in above scenario but no progress..

https://<instance>content.force.com/sfc/servlet.shepherd/version/download/<ContentVerion record Id>

Eg: https://c.ap1.content.force.com/sfc/servlet.shepherd/version/download/06890000000CZjT.