Urban Legend? Must Return PageReference To Rerender

Analysis

Conclusion

You do not need to return a PageReference for rerender to understand when the action has completed. So if you have a method that will never cause a redirect, you can make it void after all. Still looking for documentation one way or the other. At the bottom I have included my code used to support this conclusion. All four buttons in the example act the same.

Documentation

@Mohith Shrivastava answered a similar (but not exact) question in the thread pagereference return null vs void.

Returning Null will not refresh the view state. Unless we explicitly say that setredirect(true) the view state will be maintained. An action method with no return type (void) will not reset the view state.

The supporting link is, unsurprisingly, broken. And whether or not the view state gets refreshed does not actually answer the question of whether or not a rerender will take place.

In the comments, @sfdcfox added:

You should return void if there is no possibility of a redirect. This makes it clear to other developers that may later view the source code that there will be no redirect from this action function without examining the entire function. This is useful when the function spans hundreds of lines and includes complex control structures. In the application I am working on finishing up, the prior developer always returned a null page reference instead of using void, and it significantly slowed down my progress.

Again, it doesn't really address the rerender issue, but it might be the closest we get to official documentation.


Evidence

Controller

public class Example
{
    public Integer calls
    {
        get
        {
            calls = (calls == null) ? 1 : ++calls;
            return calls;
        }
        private set;
    }
    public PageReference doSomething() { return null; }
    public void doNothing() { }
}

Page

<apex:page controller="Example">
    <apex:outputPanel id="example">
        <apex:outputText value="{!calls}" />
    </apex:outputPanel>
    
    <apex:form>
        <apex:commandButton value="Increment" action="{!doSomething}" rerender="example" />
        <apex:commandButton value="Increment" action="{!doNothing}" rerender="example" />
        
        <apex:commandButton value="Increment" action="{!doSomething}" />
        <apex:commandButton value="Increment" action="{!doNothing}" />
    </apex:form>
</apex:page>

Its clear to me that one can rerender what they want whether they return a pagereference or not. I'd cite the many methods used as getters and/or setters that are not pagereferences which can be used to rerender as much or as little of a page as one desires. It all depends entirely on what you set in your commandButton.

<apex:commandButton value="MySelected" action="{!getSelected}" rerender="AsMuchAsIWant" ></apex:commandButton>

public list<string> getSelected()
{
  // do something with list
  // return is optional 
  // method could have been void
}

In fact, the documentation discusses this in the section on Using Ajax in a Page. The behavior we're talking about in terms of partial page updates is primarily what Salesforce views as an Ajax Event. Three examples are provided in the above section of how those can occur using standard controllers without any Extensions or Custom Controllers.

I'll add that my reading of the PageReference Class is that it's purpose is for navigation. I don't see anything written in the documentation about using it for page refreshes. All of that information falls under Order of Execution in a Visualforce Page which is a subtopic of Custom Controllers and Controller Extensions and seems to be related to callbacks.


Along with the other answers here, in the VF doc on commandButton, the action= attribute is optional. The same is true for commandLink, actionSupport and actionFunction

Hence, the rerendering (i.e. AJAX refresh) is determined by the presence of the rerender= attribute. Thus, no particular signature is required for the controller action method as the controller action method is not even required! This, as @crmprogdev points out, would be typical in a VF page that just used a standardController.

So, put this alleged requirement on Snopes.