There are quite a few blogs describing a means to build Salesforce URL’s to standard pages for creating records, that can be applied to Custom Buttons in order to pre-populate field values when a user clicks a button. For example replacing the New button on a Related list.
- Salesforce URL Hacking to Prepopulate Fields on a Standard Page Layout
- Hack to find field ids – allows a default UI “New” page to be pre-populated
- Salesforce URL Hacking (Properly)
- Create a Custom ‘New’ Button on a Related List to Return to the Parent Record After Clicking Save
IMPORTANT NOTE: The URL format Salesforce uses for the standard UI is not a supported API and thus subject to change. Though it has become quite common practice in order to improve the usability of the standard UI.
Making things a little more Robust
Other than URL format assumption, there is an area of further fragility shared amongst the solutions I’ve seen to-date. Which is how to obtain and manage the custom field Id’s needed on the URL’s (since they don’t take field API names). Either via discovering these manually or dynamically via using REGEX parsing of the HTML source code of the Salesforce standard pages. Although there is a Salesforce IdeaExchange submission to have Salesforce expose these Id’s via Apex Describe, it apparently has not been addressed… or so it would seem that is….
Tooling API support for Custom Object and Custom Fields
Probably the least obvious aspect of the Tooling API is its ability to actually query (via REST or SOAP) the CustomObject and CustomField objects (which are not accessible via Apex SOQL). As we know every object in Salesforce has an ID, this got me wondering if in this case its the same ID’s needed by the approaches used above. And thus if so, would serve as a more supported and less risky means to obtain the custom field Id’s. I have also wanted to start building out a Apex wrapper for the Tooling API for a while now. The following Apex code shows the library in action…
UPDATE: Please use the Apex code that wraps the REST version of the API in order to be compatible with the statements in this blog.
// Constructs the Tooling API wrapper (default constructor uses user session Id) ToolingAPI toolingAPI = new ToolingAPI(); // Query CustomObject object by DeveloperName (note no __c suffix required) List<ToolingAPI.CustomObject> customObjects = (List<ToolingAPI.CustomObject>) toolingAPI.query('Select Id, DeveloperName, NamespacePrefix From CustomObject Where DeveloperName = \'Test\'').records; // Query CustomField object by TableEnumOrId (use CustomObject Id not name for Custom Objects) ToolingAPI.CustomObject customObject = customObjects; Id customObjectId = customObject.Id; List<ToolingAPI.CustomField> customFields = (List<ToolingAPI.CustomField>) toolingAPI.query('Select Id, DeveloperName, NamespacePrefix, TableEnumOrId From CustomField Where TableEnumOrId = \'' + customObjectId + '\'').records; // Dump field names (reapply the __c suffix) and their Id's System.debug(customObject.DeveloperName + '__c : ' + customObject.Id); for(ToolingAPI.CustomField customField : customFields) System.debug( customObject.DeveloperName + '__c.' + customField.DeveloperName + '__c : ' + customField.Id);
This results in the following list of fields and Id’s against my test custom object…
00:27:38.845 (845882069)|USER_DEBUG||DEBUG|Test__c : 01IG00000021cXoMAI 00:27:38.846 (846249350)|USER_DEBUG||DEBUG|Test__c.A_Number__c : 00NG0000009Y0I9MAK 00:27:38.846 (846305290)|USER_DEBUG||DEBUG|Test__c.Colours__c : 00NG0000009prwyMAA 00:27:38.846 (846328856)|USER_DEBUG||DEBUG|Test__c.Date__c : 00NG0000009BrnxMAC 00:27:38.846 (846513094)|USER_DEBUG||DEBUG|Test__c.Message__c : 00NG0000009Y0IOMA0 00:27:38.846 (846535746)|USER_DEBUG||DEBUG|Test__c.MultiPick__c : 00NG000000AcULrMAN 00:27:38.846 (846558753)|USER_DEBUG||DEBUG|Test__c.MyCheckbox__c : 00NG0000009Y5C8MAK 00:27:38.846 (846741056)|USER_DEBUG||DEBUG|Test__c.RichText__c : 00NG0000009XaRJMA0 00:27:38.846 (846816183)|USER_DEBUG||DEBUG|Test__c.Text__c : 00NG0000009prxwMAA
This blog serves as a means to demonstrate an initial starting point for a Apex wrapper around the Tooling API (the GitHub repo has the full code with tests to deploy direct via the usual link). Be sure to setup the appropriate Remote Site setting for the Tooling API end point (easiest way is to run the code and note the URL given in the exception). Finally a means for for the various authors of the solutions above to update their code. Enjoy!