Demystifying the PageReference

The PageReference is one of the most commonly used classes in Visualforce programming. In general, an instance of the PageReference class can be used to refer to another web page. This may be another Visualforce page, another standard page, or, it could be a web page outside your Salesforce org. The PageReference object functions less as a page reference mechanism, and more as a page redirection mechanism.

Action methods

In Visualforce, you can define action methods using the <apex:commandButton> and other tags. These action methods allow you to define certain tasks that should be carried out when the corresponding button or link is clicked on a visualforce page. One of the main differences between an action method and a regular method is that an action method should return an object of type PageReference upon completion. You can define an action method as returning nothing (void), but that is equivalent to returning a NULL PageReference object.

PageReference in action

In order to understand how the PageReference is used for page redirection in Visualforce, let us look at a simple example. I have created a simple Visualforce page that has a single commandbutton, which invokes an action method on the controller called "saveMethod()". The saveMethod returns a new PageReference object, that is instantiated as a reference to www.google.com.

Visualforce Page

    
     
 


Apex Controller
public class MyPage_Controller {
 public PageReference saveMethod()
    {
  PageReference pgref = new PageReference('http://www.google.com');
        pgref.setRedirect(true);
        return pgref;
    }
}

Create both the Visualforce page and controller above in your org. Browse to the Visualforce page and click the "Click Me" button. You should be automatically redirected to the google home page.

What's going on under the hood

In order to better understand what was going on, I tried to analyze the redirect using Fiddler. For those of you who are hearing about it for the first time, Fiddler is a web traffic analysis tool that allows you to look at the request/responses(and much more) of all web traffic on your computer. So, using Fiddler, I looked at the page submit action that happened when I clicked on the "Click Me" button, and this is what I saw :-



In the above screenshot, the top portion is indicates the "request", whereas the bottom portion indicates the "response". Look at the highlighted block in the top portion - this shows that the page /apex/MyPage was submitted via a POST request. The response is more interesting - the page returned a piece of javascript as the response, which basically did the job of redirecting the user to www.google.com (window.location.replace('http://www.google.com')).

To summarize, here's what happened-
A. User clicks on the button to submit the page via HTTP POST
B. The controller method "saveMethod" is executed, and the method returns a PageReference to www.google.com.
C. Visualforce detects the PageReference, and returns a script as a response that immediately redirects the user to www.google.com.

Redirecting to another page within Salesforce

Let us tweak the code a little bit to see what happens when the PageReference points to a Salesforce standard page. Replace your controller method with the below:-

Apex Controller
public class MyPage_Controller {
 public PageReference saveMethod()
    {
        Account acc = [select Id, Name from Account LIMIT 1];
        // Redirect to an account
  PageReference pgref = new PageReference('/' + acc.Id);
        pgref.setRedirect(true);
        return pgref;
    }
}

Checkout the Fiddler logs now -



As you can see from the highlighted response, the POST request again returned a javascript response that redirected the user to the correct account page. So, in most cases, the "modus operandi" here is that whenever you return a PageReference object from an action method, Salesforce sends some javascript as a response which redirects the user to another page. I said "in most cases" because there are some exceptions to this rule.

The setRedirect method

The PageReference class also provides the setRedirect method, that allows you to set the "redirect" flag to true or false. The Salesforce documentation on the use of setRedirect is quite ambiguous.
This page states that "Notice in the code above that the redirect attribute for the PageReference is set to true. If this attribute is not set, the PageReference is returned to the browser, but no navigation occurs—the URL for the original page remains the same. If you want to change the URL as a result of navigation, you have to set the redirect attribute". As we will see in a little bit, this is misleading. A more accurate description can be found at this page, which states that "If set to false, the redirect is a server-side forward that preserves the view state if and only if the target page uses the same controller and contains the proper subset of extensions used by the source page".

In order to understand the behavior of the setRedirect method, let us create a second Visualforce page that uses the same controller. We will then modify the controller "saveMethod" so that upon clicking the button on the first page, you will be redirected to the second page.

Second VF Page

    
     Hello, this is the second page.
     


Apex Controller
public class MyPage_Controller {
 public PageReference saveMethod()
    {
        // Checkout how you can refer to an existing VF page with Page.[VF Page Name]
  PageReference pgref = Page.MyPage_II;
        pgref.setRedirect(true);
        return pgref;
    }
}

If you look at the Fiddler logs now, it's similar to the previous ones, wherein a redirect is performed via client-side javascript.



However, let us now change the setRedirect to "false", and see the results.
public class MyPage_Controller {
 public PageReference saveMethod()
    {
  PageReference pgref = Page.MyPage_II;
        pgref.setRedirect(false);
        return pgref;
    }
}



Surprise, surprise. Instead of doing a client-side redirect, Salesforce did a server-side redirect and returned the HTML for the new page in the response. Note that the server-side redirect was done in this case because the MyPage_II page shared the same controller as the original page. So, the rule is if the page to which the redirect happens shares the same controller as the page that did the redirect, then Salesforce will do a server-side redirect. In all other cases, a client-side redirect is done by sending the redirection javascript in the response.

With that, I'm wrapping up my post on the PageReference. Hope you found it helpful.

No comments:

Post a Comment