Wednesday, March 30, 2016

Salesforce IDE superpowers uncovered

Disclaimer: I've been informed by Salesforce that this an exceptional case for functionality is still being refined and will likely be exposed broadly in a future API version (#SafeHarbour). Although perhaps not in this exact form. As with all undocumented API features they could disappear at any time in a future release.

Borrowing the Warranty phrasing from Scott Hanselman:
Of course, this is just some dude's blog. Depending on undocumented API functionality is a recipe for losing your job and a messy divorce. Salesforce are likely to make changes to the existing functionality between major releases. As they don't know you are using this functionality they won't tell you. There's no warranty, express or implied. I don't know you and I don't how how you got here. Stop calling. Jimmy no live here, you no call back! [My current landline phone number used to belong to a Thai takeaway shop - True Story]

My blog disclaimer also applies.

In putting together an answer to a Salesforce StackExchange question I came across something odd with the IDE source code. The question needed a way to find details about installed packages.

I knew from my keyprefix list that InstalledPackageVersion existed. It wasn't, however, exposed via SOQL to the Partner API or Tooling API. So why then when I was Googling around does it show up in the source code for the IDE in a SOQL query?:

    // P A C K A G E S
    DEVELOPMENT_PACKAGES("SELECT Id, Name, Description, IsManaged FROM DevelopmentPackageVersion"),
    INSTALL_PACKAGES("SELECT Id, Name, Description, IsManaged, VersionName FROM InstalledPackageVersion"),

What makes the IDE so special that it can run SOQL queries that other API users can't?

The answer lies in the SOAP API CallOptions.client header. The docs say this is "A string that identifies a client.". I've used it before in the past after passing the app exchange security review to access the Partner API in professional edition orgs. It turns out this is also the key to accessing the hidden abilities of the IDE. Again from the source code for the IDE:

    //value is critical for Eclipse-only API support
    private final String clientIdName = "apex_eclipse";

This is later combined with the API version to create the callOptions header.

So what if we use the same string when we establish our Session using the Partner API and then on subsequent calls?

The FuseIT SFDC Explorer supports setting the Client Id on the login New Connection screen and on a saved connection string.

   <add name="ForceCom IDE Login" 

The raw SOAP POST request:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="" xmlns:xsi="" xmlns:xsd="">
    <CallOptions xmlns="">
    <SessionHeader xmlns="">
    <-- etc... -->

Now we be access to additional sObject Types that were previously inaccessible. So far I've tried:

  • DevelopmentPackageVersion
  • InstalledPackageVersion
  • ApexClassIdentifier
  • ApexClassIdentifierRelationship

I'll do some more poking around as time permits to see if there are any other hidden treasures.

Friday, March 4, 2016

FuseIT SFDC Explorer 3.0.16053.2

The latest v3.0 release of the FuseIT SFDC Explorer now supports TLS 1.1 and 1.2. This was required as Salesforce will be disabling TLS 1.0 via critical updates available in Spring '16.

Part of this was to upgrade to the .NET Framework 4.6.1 to get native support for the newer TLS versions. You can get the .NET Framework 4.6.1 installer from Note that it does need to be 4.6.1, the 4.6 installer won't work.

Without this version you are likely to get an error like the following when attempting to login:

UNSUPPORTED_CLIENT: TLS 1.0 has been disabled in this organization. Please use TLS 1.1 or higher when connecting to Salesforce using https.

Other notable changes:

  • Update ApexLog parsing to allow for Spring '16 date formats
  • Wsdl2Apex: Add basic WSDL schema validation and reporting via error messages. Detect potential WSDL 1.1 structure issues.
  • Wsdl2Apex: Apex variable names can't start with an underscore. Will be prefixed with 'x'