Retrieve salesforce instance URL instead of visualforce instance
Asked Answered
W

8

14

From a visualforce page, I need to retrieve our organization's salesforce instance's URL, and not the visual force URL.

For example I need https://cs1.salesforce.com instead of https://c.cs1.visual.force.com

Here's what I've tried so far and the outcome I got:

Accessed the Site global variable from the VF Page:

<apex:outputText value="{!$Site.Domain}" /> returns null

Sidenote: Everything in $Site.xxx seems to return null.

From the Apex controller:

public String getSfInstance()
{
  return ApexPages.currentPage().getHeaders().get('Host');
}

and

public String getSfInstance()
{
  return URL.getSalesforceBaseUrl().toExternalForm();
}

returns c.cs1.visual.force.com and https://c.cs1.visual.force.com, respectively.

Question: How do I retrieve what I want: https://cs1.salesforce.com?

Woodall answered 20/2, 2012 at 22:52 Comment(1)
$Site is only for salesforce sites (developer.force.com/sites)Schutt
I
11

Here's something that I used within my Apex Trigger

System.URL.getSalesforceBaseUrl().getHost().remove('-api' );

This gives me proper URL

Injector answered 10/12, 2012 at 9:24 Comment(1)
As of Winter'19 there's a new function available that works without relying on brittle string manipulation - System.URL.getOrgDomainUrl().toExternalForm()Crescin
S
4

This is a known issue, the URL.getSalesforceBaseUrl() should provide this information but it does not. However in reality this has very limited functional impact.

Their instance and apex domains are interchangeable in the sense that requesting a URL that does not belong to one gets redirected to the other.

for example if you seek /apex/myPage from cs1.salesforce.com you'll get redirected to c.cs1... and vise versa requesting /ID from apex domain will get you redirected to instance domain (unless detail action has been overridden)

If this does not help you there is one workaround, albeit very ugly :) create a custom object to store the base url and create before insert/update trigger which will set the baseURL field to URL.getSalesforceBaseUrl().toExternalForm(). Apparently trigger is the only place on the platform where this will work (aside from execute anonymous which is not of much use). When setting up the app insert something into that table and later use SOQL to retrieve base url.

Schutt answered 21/2, 2012 at 9:12 Comment(1)
Redirection between c.cs1... and cs1.salesforce.com works great except any anchor information (c.cs1.../apex/test#myAnchorInformation) seem to be removed in certain browsers such as Safari on ipad. This means that in situations with anchor values, it's not possible to rely on the platform redirect.Balky
D
4

Here is an Apex property that you can throw into a Utility class that will reliably return the instance for your org. Using this, you can easily construct your organization's Salesforce URL by appending ".salesforce.com" to the Instance:

public class Utils {

 // Returns the Salesforce Instance that is currently being run on,
 // e.g. na12, cs5, etc.
public static String Instance {
    public get {
        if (Instance == null) {
            //
            // Possible Scenarios:
            //
            // (1) ion--test1--nexus.cs0.visual.force.com  --- 5 parts, Instance is 2nd part
            // (2) na12.salesforce.com      --- 3 parts, Instance is 1st part
            // (3) ion.my.salesforce.com    --- 4 parts, Instance is not determinable

            // Split up the hostname using the period as a delimiter
            List<String> parts = System.URL.getSalesforceBaseUrl().getHost().replace('-api','').split('\\.');
            if (parts.size() == 3) Instance = parts[0];
            else if (parts.size() == 5) Instance = parts[1];
            else Instance = null;
        } return Instance;
    } private set;
}

// And you can then get the Salesforce base URL like this:
public static String GetBaseUrlForInstance() {

     return 'https://' + Instance + '.salesforce.com';

}

FYI: For Scenario (1), the 1st of the 4-part hostname can get really complicated, but you'll always be able to find the Instance name as the 2nd part. For those who are interested, the syntax of Scenario 1 follows this pattern:

     <MyDomain>--<SandboxName>--<Namespace>.<Instance>.visual.force.com
Darwindarwinian answered 15/3, 2012 at 15:3 Comment(0)
R
3

Here you have a quite nice and small snippet, that does, what it should for VisualforcePages :-)

        String sUrlRewrite = System.URL.getSalesforceBaseUrl().getHost();
        //  Example: c.cs7.visual.force.com
        sUrlRewrite = 'https://'
                + sUrlRewrite.substring(2,6) 
                + 'salesforce.com'
                + '/'
                + recordId;

// Returns: https://cs7.salesforce.com/00kM00000050jFMIAY

Rothrock answered 4/8, 2012 at 13:54 Comment(1)
Instance could be cs87 or eu3, In this case hardcoded numbers won't work. Also as mentioned by zachelrath, we could have domain name. So, this would fail in such scenarios.Meaty
G
3

Use:    Url.getOrgDomainUrl().toExternalForm()

Thanks, Tim Lewis


Note behaviour changes between releases and is sensitive to My Domain settings:

  • @Future context returns https://na1.salesforce.com
  • Visualforce context returns https://na1.salesforce.com
  • Force.com Site context returns https://na1.salesforce.com
  • @Future context returns https://mydomain.my.salesforce.com
  • Visualforce context returns https://mydomain.my.salesforce.com
  • Force.com Site context returns https://mydomain.my.salesforce.com

My Domain is mandatory in new orgs effective Winter '21.
Enhanced Domains is mandatory in all orgs effective Summer '22.

// Not to be confused with Url.getSalesforceBaseUrl()
// http://na1.salesforce.com (can happen in async apex)
// https://c.na1.visual.force.com (local Visualforce Page)
// https://ns.na1.visual.force.com (packaged Visualforce Page)
// https://custom.my.salesforce.com (org has My Domain enabled)
// https://sandbox-mydomain.na1.force.com (sandbox site with My Domain...)

See also the Salesforce Identity API which attests the pod/instance endpoint.

Gainer answered 28/12, 2014 at 22:0 Comment(2)
This works except for the case when the code is called from a trigger. Unfortunately.Cosset
As of Winter'19 there's finally a simple solution: System.URL.getOrgDomainUrl().toExternalForm()Crescin
T
0

Fix to Alex_E snippet:

    String sUrlRewrite = System.URL.getSalesforceBaseUrl().getHost();
    String sfBaseProtocol = System.URL.getSalesforceBaseUrl().getProtocol();

    //remove namespace
    integer firstDotPos = sUrlRewrite.indexOf('.');
    sURlRewrite = sURlRewrite.substring(firstDotPos+1);

    //replace visual.force with salesforce
    sURlRewrite = sURlRewrite.replace('visual.force', 'salesforce');
    sUrlRewrite = sfBaseProtocol+'://'+sURlRewrite;

serverURL = sUrlRewrite;
Towpath answered 3/6, 2013 at 17:14 Comment(0)
E
0

This works for me:

String sUrlRewrite = System.URL.getSalesforceBaseUrl().getProtocol() 
    + '://' + System.URL.getSalesforceBaseUrl().getHost() 
    + '/' + record.Id;
Escuage answered 11/5, 2015 at 12:16 Comment(0)
Q
0

Here is something to do with regex

public String getURL() {
    return String.format(
      'https://{0}.salesforce.com',
      new String[]{
        URL.getSalesforceBaseUrl().getHost().substringAfter('.').substringBefore('.')
      });
}
Quadrireme answered 18/2, 2016 at 1:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.