Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
DictionaryCController Extension
DevelopmentAdvanced

Controller Extension

A Controller Extension is an Apex class that layers extra logic and methods onto a Visualforce standard controller without replacing it.

§ 01

Definition

A Controller Extension is an Apex class that layers extra logic and methods onto a Visualforce standard controller without replacing it. The extension is declared on the Visualforce page tag with the extensions attribute, alongside the standardController attribute. When the page loads, the platform constructs the standard controller for the target object (Account, Opportunity, or any custom object) and then constructs the extension, passing the standard controller into the extension's constructor as ApexPages.StandardController.

Extensions exist because standard controllers handle common patterns (load, save, delete, edit) but cannot reach beyond the object's own fields and the user's view state. An extension adds custom action methods, computed properties, related-object queries, and integration hooks. The relationship is composition, not replacement: the standard controller continues to power the save and edit cycle, while the extension supplies whatever the page needs that the platform did not predict.

§ 02

How a Controller Extension actually pairs with a standard controller

Why extensions exist alongside standard controllers

The standard controller for an object handles object-specific defaults: a save button, a cancel button, the view state for the current record, validation against the page layout. It does not know about related objects, custom calculations, or external services. A controller extension fills that gap. The page tag specifies both: standardController="Account" extensions="AccountSidebarExt". The platform wires them together at page load. You get the convenience of the standard controller without losing the ability to add custom Apex.

The extension constructor

An extension class must define a constructor that takes ApexPages.StandardController (or ApexPages.StandardSetController for list views). Inside the constructor, you typically capture the standard controller in an instance variable and call standardController.getRecord() to access the current sObject. The constructor is also where you query related data and initialize page-bean state. The constructor runs once per page load. Initialization is cheap because everything fits in one transaction.

Multiple extensions on one page

The extensions attribute accepts a comma-separated list of class names: extensions="ExtA,ExtB,ExtC". The platform constructs each extension in order, and each one has its own scope and methods. The page can reference methods on any extension by class name. Multiple extensions are useful for splitting a complex page into focused units: one extension for the address widget, another for the related-cases list, another for the integration hook. The pattern keeps each extension class small and testable.

Action methods and PageReference returns

Extension methods bound to UI buttons typically return PageReference. A PageReference can be the current page (return null to stay), a redirect to another page (Page.SuccessPage), or a callback URL parameter. Returning a PageReference with setRedirect(true) navigates the browser to the target URL. Returning null leaves the user on the current page with updated state. This is how Visualforce pages built on extensions handle save-and-go-to-next or save-and-stay workflows.

Sharing context and security

Like any Apex class, an extension defaults to system context unless declared with sharing. Mixing with sharing extensions with without sharing helper classes is the most common security review finding in Visualforce code. The extension's sharing mode also affects what the standard controller returns: if the running user does not have read access to a related field, the extension cannot promote that field into the page bean without bypassing sharing explicitly. Default to with sharing on extensions and add specific helper classes for the few methods that need elevated access.

View state and the 170 KB cap

Visualforce serializes the controller state (including extension state) into a hidden form field on every page render. The view state has a hard 170 KB cap. Extensions that store large collections in instance variables are the leading cause of view state overflow errors. Use the transient keyword on instance variables that hold data the page does not need to keep across postbacks. Move bulk processing to async Apex (queueable, future) instead of holding intermediate results in the extension class.

Testing a controller extension

To test an extension, instantiate the standard controller manually with ApexPages.StandardController sc = new ApexPages.StandardController(testRecord), pass it into the extension's constructor, and call the action methods. ApexPages.currentPage().getParameters().put('id', testRecord.Id) lets you fake URL parameters. The pattern feels verbose but is straightforward. The reward is a test class that exercises both the standard-controller integration and the custom extension logic.

§ 03

Writing a Controller Extension for a Visualforce page

Creating a controller extension is a two-step process: write the Apex class with the standard controller constructor, then reference it from the Visualforce page tag's extensions attribute. The framework handles the wiring.

  1. Identify the standard controller

    Decide which object the Visualforce page targets: Account, Case, or any custom object. The page tag will declare standardController="ObjectName". Custom objects use their API name (My_Object__c).

  2. Create the extension Apex class

    From the Developer Console or CLI, create a new Apex class. Add a public with sharing class declaration. Define a constructor that takes ApexPages.StandardController and store it in an instance variable.

  3. Add action methods and properties

    Inside the extension, write public methods for any custom button actions, and public properties for any computed values the page should display. Action methods return PageReference (or void for buttons that do not navigate).

  4. Reference the extension from the Visualforce page

    Open the Visualforce page and update the page tag: <apex:page standardController="Account" extensions="AccountExtension">. Multiple extensions are comma-separated.

  5. Reference extension methods from the markup

    Inside the page, bind buttons to extension methods with action="{!methodName}". Reference properties with {!propertyName}. The platform resolves the names against the standard controller first, then the extensions in declaration order.

  6. Write the test class

    Create an Apex test class. Insert a sample record, build the standard controller manually with new ApexPages.StandardController(record), instantiate the extension, and call each action method asserting the returned PageReference or state mutation.

Key options
standardControllerremember

Attribute on the Visualforce page tag that picks the object whose standard controller backs the page. Cannot be combined with the controller attribute.

extensionsremember

Comma-separated list of Apex class names that extend the standard controller. Each class must have a constructor accepting ApexPages.StandardController.

ApexPages.StandardControllerremember

The system class representing the standard controller. The extension constructor captures it and uses its methods (getRecord, save, edit, cancel).

ApexPages.StandardSetControllerremember

The system class for list-view standard controllers. Extensions on list views take this type in the constructor instead.

transient keywordremember

Modifier on instance variables that excludes them from view state serialization, keeping the page under the 170 KB cap.

PageReferenceremember

Return type used by action methods. Setting setRedirect(true) navigates the browser. Returning null keeps the user on the same page.

Gotchas
  • Extensions are constructed every page load. Heavy queries in the constructor inflate page-load time. Move expensive work to lazy properties evaluated on first access.
  • View state exists per page render. Storing large lists in non-transient instance variables triggers the 170 KB overflow error. Mark intermediate collections transient.
  • Declaration order in the extensions attribute matters for name resolution. If two extensions define a method with the same name, the first one wins.
  • The standard controller and the extension share sharing context only if the extension class declares with sharing. Without it, the extension runs in system mode regardless of the page user.
  • Controller extensions are a Visualforce concept. Lightning Web Components and Aura Components do not use extensions. The equivalent pattern in Lightning is an Apex class with @AuraEnabled methods called from the component.
§

Trust & references

Sources

Cross-checked against the following references.

Official documentation

Straight from the source - Salesforce's reference material on Controller Extension.

Keep learning

Hands-on resources to go deeper on Controller Extension.

Was this entry helpful?
Help us write better definitions. Quick reactions or detailed edit suggestions.

About the Author

Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.

§

Test your knowledge

Q1. What is a Controller Extension?

Q2. What attribute on a Visualforce page references extensions?

Q3. What's the key advantage of Controller Extensions over Custom Controllers?

§

Discussion

Loading…

Loading discussion…