[SalesForce] Returning PageReferences from Init – Not working in sandbox

So either I'm going nuts, or I'm overlooking something obvious, or I'm just encountering some very weird behaviour.

The Setup

I have a page which calls an Init action in the controller from the page tag

<apex:page controller="myController" action="{!Init}">

The Init() method returns a PageReference.

I'm using some of Michaelforce's code to detect whether or not I'm in a sandbox environment, and if so I return a page reference to redirect the user. If not, I just return null so that the page loads as normal.

public PageReference Init()
{
    if(WhereAmI.IsSandbox())
    {
        PageReference pr = Page.PackPrefix__OtherPage;
        return pr.setRedirect(true);
    }

    return null;
}

The Problem

This code works in my development environment, i.e. it doesn't redirect. If i change my if statement for testing to if(!WhereAmI.IsSandbox()) then it correctly redirects also.

Once I package the code up and install the package (managed) in a sandbox, it does not redirect. I made the WhereAmI class and its methods global so that I could test them in Execute it's functioning perfectly, returning true and yet I don't get redirected.

The page does have a different content type to normal but I don't think that's the issue given that it works in production. So the quesiton: have I missed something that's right under my nose, or does this smell like a bug?

Best Answer

URL.getSalesforceBaseUrl is execution context sensitive. The code you've linked to uses URL.getSalesforceBaseUrl(). This actually returns a different Salesforce base URL dependent on the context you run it from.

Possible Issue. While you've tested the function itself from a Sandbox environment and it returns true. I am wondering if that is from Developer Console / Execute Anonymous? Call this method from these contexts will typically return what you expect. As in what you typically see in your browser URL when your looking at a native page, e.g.

https://na7.salesforce.com

However when called from a VF controller execution context the URL returned is the VF URL including your namespace. I don't have a sandbox with a managed package containing this code to hand to test this theory, but I think the problem lies in how its parsing the host name part of the URL.

String server = host.substring(0,host.indexOf('.'));

So a base URL like this would return your namesapce prefix as the server.

https://namespace.na7.visual.force.com/apex/myVFPage

Summary: So I think the issue is that the isSandbox method is not considering the type of host name returned in a VF context. Note that in an unmanaged environment the host name part of the URL will be c.na7.visual.force.com. So you really just need to check for 'visual.force' in the URL, then skip the second part of the server name. If your not in a VF context, the existing code will work.

Working Code:

String server = host.contains('visual.force.com') ? host.split('\\.')[1] : host.split('\\.')[0];