Custom Controllers and Controller Extensions. salesforce Visualforce Developer Guide
Below you will find brief information for Visualforce Developer Guide. The guide offers comprehensive details on Visualforce which allows developers to build sophisticated user interfaces for Salesforce applications, providing deep customization and control over the user experience.
Advertisement
Advertisement
CHAPTER 7
Custom Controllers and Controller Extensions
Standard controllers can provide all the functionality you need for a Visualforce page because they include the same logic that is used for a standard page. For example, if you use the standard Accounts controller, clicking a Save button in a Visualforce page results in the same behavior as clicking Save on a standard Account edit page.
However, if you want to override existing functionality, customize the navigation through an application, use callouts or Web services, or if you need finer control for how information is accessed for your page, you can write a custom controller or a controller extension using Apex:
•
What are Custom Controllers and Controller Extensions?
•
•
Building a Controller Extension
•
•
•
Considerations for Creating Custom Controllers and Controller Extensions
•
Order of Execution in a Visualforce Page
•
Testing Custom Controllers and Controller Extensions
•
Validation Rules and Custom Controllers
•
Using the transient
Keyword
What are Custom Controllers and Controller Extensions?
A custom controller is an Apex class that implements all of the logic for a page without leveraging a standard controller. Use custom controllers when you want your Visualforce page to run entirely in system mode, which does not enforce the permissions and field-level security of the current user.
A controller extension is an Apex class that extends the functionality of a standard or custom controller. Use controller extensions when:
•
You want to leverage the built-in functionality of a standard controller but override one or more actions, such as edit, view, save, or delete.
•
You want to add new actions.
•
You want to build a Visualforce page that respects user permissions. Although a controller extension class executes in system mode, if a controller extension extends a standard controller, the logic from the standard controller does not execute in system mode.
Instead, it executes in user mode, in which permissions, field-level security, and sharing rules of the current user apply.
Note:
Although custom controllers and controller extension classes execute in system mode and thereby ignore user permissions and field-level security, you can choose whether they respect a user's organization-wide defaults, role hierarchy, and sharing rules by using the with sharing
keywords in the class definition. For information, see “Using the with sharing
or without sharing
Keywords” in the
Apex Developer Guide
.
86
Custom Controllers and Controller Extensions Building a Custom Controller
Building a Custom Controller
A custom controller is an Apex class that uses the default, no-argument constructor for the outer, top-level class. You cannot create a custom controller constructor that includes parameters.
To create a custom controller:
1. From Setup, enter
Apex Classes
in the
Quick Find
box, then select Apex Classes.
2. Click New.
3. Click Version Settings to specify the version of Apex and the API used with this class. If your organization has installed managed packages from the AppExchange, you can also specify which version of each managed package to use with this class. Use the default values for all versions. This associates the class with the most recent version of Apex and the API, as well as each managed package.
You can specify an older version of a managed package if you want to access components or functionality that differs from the most recent package version. You can specify an older version of Apex and the API to maintain specific behavior.
4. In the class editor, enter the Apex code for the class. A single class can be up to 1 million characters in length, not including comments, test methods, or classes defined using
@isTest
.
5. Click Save to save your changes and return to the class detail screen, or click Quick Save to save your changes and continue editing your class. Your Apex class must compile correctly before you can save your class.
The following class is a simple example of a custom controller: public class MyController { private final Account account; public MyController() { account = [SELECT Id, Name, Site FROM Account
WHERE Id = :ApexPages.currentPage().getParameters().get( 'id' )];
} public Account getAccount() { return account;
} public PageReference save() { update account; return null ;
}
}
The following Visualforce markup shows how the custom controller above can be used in a page:
<apex:page controller= "myController" tabStyle= "Account" >
<apex:form >
<apex:pageBlock title= "Congratulations {!$User.FirstName}" >
You belong to Account Name: <apex:inputField value= "{!account.name}" />
<apex:commandButton action= "{!save}" value= "save" />
</apex:pageBlock >
</apex:form >
</apex:page >
The custom controller is associated with the page because of the controller
attribute of the
<apex:page >
component.
87
Custom Controllers and Controller Extensions Building a Custom Controller
As with standard controllers and controller extensions, custom controller methods can be referenced with
{! }
notation in the associated page markup. In the example above, the getAccount
method is referenced by the
<apex:inputField >
tag's value
attribute, while the
<apex:commandButton >
tag references the save
method with its action
attribute.
Note: Like other Apex classes, all custom controllers run in system mode. Consequently, the current user's credentials are not used to execute controller logic, and the user's permissions and field-level security do not apply.
You can choose whether a custom controller respects a user's organization-wide defaults, role hierarchy, and sharing rules by using the with sharing
keywords in the class definition. For information, see “Using the with sharing
or without sharing
Keywords” in the
Apex Developer Guide
.
A custom controller can also be used to create new records. For example: public class NewAndExistingController { public Account account { get; private set; } public NewAndExistingController() {
Id id = ApexPages.currentPage().getParameters().get( 'id' ); account = (id == null ) ?
new Account() :
[SELECT Name, Phone, Industry FROM Account WHERE Id = :id];
} public PageReference save() { try { upsert (account);
} catch (System.DMLException e) {
ApexPages.addMessages(e); return null ;
}
// After successful Save, navigate to the default view page
PageReference redirectSuccess = new ApexPages.StandardController(Account).view(); return (redirectSuccess);
}
}
The following Visualforce markup shows how the custom controller above can be used in a page:
<apex:page controller= "NewAndExistingController" tabstyle= "Account" >
<apex:form >
<apex:pageBlock mode= "edit" >
<apex:pageMessages/ >
<apex:pageBlockSection >
<apex:inputField value= "{!Account.name}" />
<apex:inputField value= "{!Account.phone}" />
<apex:inputField value= "{!Account.industry}" />
</apex:pageBlockSection >
<apex:pageBlockButtons location= "bottom" >
<apex:commandButton value= "Save" action= "{!save}" />
</apex:pageBlockButtons >
</apex:pageBlock >
</apex:form >
</apex:page >
88
Custom Controllers and Controller Extensions Building a Controller Extension
Building a Controller Extension
A controller extension is any Apex class containing a constructor that takes a single argument of type
ApexPages.StandardController
or
CustomControllerName
, where
CustomControllerName
is the name of a custom controller you want to extend.
The following class is a simple example of a controller extension: public class myControllerExtension { private final Account acct;
// The extension constructor initializes the private member
// variable acct by using the getRecord method from the standard
// controller.
public myControllerExtension(ApexPages.StandardController stdController) { this .acct = (Account)stdController.getRecord();
} public String getGreeting() { return 'Hello ' + acct.name + ' (' + acct.id + ')' ;
}
}
The following Visualforce markup shows how the controller extension from above can be used in a page:
<apex:page standardController= "Account" extensions= "myControllerExtension" >
{!greeting} <p/ >
<apex:form >
<apex:inputField value= "{!account.name}" /> <p/ >
<apex:commandButton value= "Save" action= "{!save}" />
</apex:form >
</apex:page >
The extension is associated with the page using the extensions
attribute of the
<apex:page >
component.
As with all controller methods, controller extension methods can be referenced with
{! }
notation in page markup. In the example above, the
{!greeting}
expression at the top of the page references the controller extension's getGreeting
method.
Because this extension works in conjunction with the Account standard controller, the standard controller methods are also available.
For example, the value
attribute in the
<apex:inputField >
tag retrieves the name of the account using standard controller functionality. Likewise, the
<apex:commandButton >
tag references the standard account save
method with its action attribute.
Multiple controller extensions can be defined for a single page through a comma-separated list. This allows for overrides of methods with the same name. For example, if the following page exists:
<apex:page standardController= "Account" extensions= "ExtOne,ExtTwo" showHeader= "false" >
<apex:outputText value= "{!foo}" />
</apex:page > with the following extensions: public class ExtOne { public ExtOne(ApexPages.StandardController acon) { }
89
Custom Controllers and Controller Extensions Building a Custom List Controller public String getFoo() { return 'foo-One' ;
}
} public class ExtTwo { public ExtTwo(ApexPages.StandardController acon) { } public String getFoo() { return 'foo-Two' ;
}
}
The value of the
<apex:outputText >
component renders as foo-One
. Overrides are defined by whichever methods are defined in the “leftmost” extension, or, the extension that is first in the comma-separated list. Thus, the getFoo
method of
ExtOne
is overriding the method of
ExtTwo
.
Note: Like other Apex classes, controller extensions run in system mode. Consequently, the current user's credentials are not used to execute controller logic, and the user's permissions and field-level security do not apply. However, if a controller extension extends a standard controller, the logic from the standard controller does not execute in system mode. Instead, it executes in user mode, in which the permissions, field-level security, and sharing rules of the current user apply.
You can choose whether a controller extension respects a user's organization-wide defaults, role hierarchy, and sharing rules by using the with sharing
keywords in the class definition. For information, see “Using the with sharing
or without sharing
Keywords” in the
Apex Developer Guide
.
Building a Custom List Controller
A custom list controller is similar to a standard list controller. Custom list controllers can implement Apex logic that you define to show or act on a set of records.
For example you can create the following custom list controller based on a SOQL query: public class opportunityList2Con {
// ApexPages.StandardSetController must be instantiated
// for standard list controllers public ApexPages.StandardSetController setCon { get { if (setCon == null ) { setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
} set;
[SELECT Name, CloseDate FROM Opportunity]));
} return setCon;
}
// Initialize setCon and return a list of records public List<Opportunity> getOpportunities() { return (List<Opportunity>) setCon.getRecords();
}
}
90
Custom Controllers and Controller Extensions Building a Custom List Controller
Note: The list of sObjects returned by getRecords()
is immutable. For example, you can’t call clear()
on it. You can make changes to the sObjects contained in the list, but you can’t add items to or remove items from the list itself.
The following Visualforce markup shows how the custom controller above can be used in a page:
<apex:page controller= "opportunityList2Con" >
<apex:pageBlock >
<apex:pageBlockTable value= "{!opportunities}" var= "o" >
<apex:column value= "{!o.Name}" />
<apex:column value= "{!o.CloseDate}" />
</apex:pageBlockTable >
</apex:pageBlock >
</apex:page >
You can also create a custom list controller that uses anti- and semi-joins as part of the SOQL query. The following code is implemented as an extension to the account standard controller: public with sharing class AccountPagination { private final Account acct;
// The constructor passes in the standard controller defined
// in the markup below public AccountPagination(ApexPages.StandardSetController controller) { this .acct = (Account)controller.getRecord();
} public ApexPages.StandardSetController accountRecords { get { if (accountRecords == null ) { accountRecords = new ApexPages.StandardSetController(
Database.getQueryLocator([SELECT Name FROM Account WHERE Id NOT IN
(SELECT AccountId FROM Opportunity WHERE IsClosed = true )]));
} return accountRecords;
} private set;
} public List<Account> getAccountPagination() { return (List<Account>) accountRecords.getRecords();
}
}
The page that displays these records uses a mix of standard list controller actions, but depends on iterating over the records returned from the custom list controller:
<apex:page standardController= "Account" recordSetVar= "accounts" extensions= "AccountPagination" >
<apex:pageBlock title= "Viewing Accounts" >
<apex:form id= "theForm" >
<apex:pageBlockSection >
<apex:dataList value= "{!accountPagination}" var= "acct" type= "1" >
{!acct.name}
</apex:dataList >
</apex:pageBlockSection >
<apex:panelGrid columns= "2" >
<apex:commandLink action= "{!previous}" >Previous </apex:commandlink >
91
Custom Controllers and Controller Extensions Controller Methods
</apex:form >
</apex:pageBlock >
</apex:page >
<apex:commandLink action= "{!next}" >Next </apex:commandlink >
</apex:panelGrid >
Controller Methods
Visualforce markup can use the following types of controller extension and custom controller methods:
•
Action
•
Getter
•
Setter
Action Methods
Action methods perform logic or navigation when a page event occurs, such as when a user clicks a button, or hovers over an area of the page. Action methods can be called from page markup by using
{! }
notation in the action
parameter of one of the following tags:
•
creates a button that calls an action
•
creates a link that calls an action
•
•
makes an event (such as “onclick”, “onmouseover”, and so on) on another, named component, call an action
•
defines a new JavaScript function that calls an action
•
calls an action when the page is loaded
For example, in the sample page in Building a Custom Controller
on page 87, the controller's save
method is called by the action parameter of the
<apex:commandButton >
tag. Other examples of action methods are discussed in Defining Action Methods
on page 119.
Getter Methods
Getter methods return values from a controller. Every value that is calculated by a controller and displayed in a page must have a
on page 87, the controller includes a getAccount
method. This method allows the page markup to reference the account
member variable in the controller class with
{! }
notation. The value
parameter of the
<apex:inputField >
tag uses this notation to access the account, and dot notation to display the account's name. Getter methods must always be named get
Variable
.
Important: It’s a best practice for getter methods to be idempotent, that is, to not have side effects. For example, don’t increment a variable, write a log message, or add a new record to the database. Visualforce doesn’t define the order in which getter methods are called, or how many times they might be called in the course of processing a request. Design your getter methods to produce the same outcome, whether they are called once or multiple times for a single page request.
92
Custom Controllers and Controller Extensions Controller Methods
Setter Methods
Setter methods pass user-specified values from page markup to a controller. Any setter methods in a controller are automatically executed before any action methods.
For example, the following markup displays a page that implements basic search functionality for Leads. The associated controller includes getter and setter methods for the search box input, and then uses the search text to issue a SOSL query when the user clicks
Go!. Although the markup doesn’t explicitly call the search text setter method, it executes before the doSearch
action method when a user clicks the command button:
<apex:page controller= "theController" >
<apex:form >
<apex:pageBlock mode= "edit" id= "block" >
<apex:pageBlockSection >
<apex:pageBlockSectionItem >
<apex:outputLabel for= "searchText" >Search Text </apex:outputLabel >
<apex:panelGroup >
<apex:inputText id= "searchText" value= "{!searchText}" />
<apex:commandButton value= "Go!" action= "{!doSearch}" rerender= "block" status= "status" />
</apex:panelGroup >
</apex:pageBlockSectionItem >
</apex:pageBlockSection >
<apex:actionStatus id= "status" startText= "requesting..." />
<apex:pageBlockSection title= "Results" id= "results" columns= "1" >
<apex:pageBlockTable value= "{!results}" var= "l" rendered= "{!NOT(ISNULL(results))}" >
<apex:column value= "{!l.name}" />
<apex:column value= "{!l.email}" />
<apex:column value= "{!l.phone}" />
</apex:pageBlockTable >
</apex:pageBlockSection >
</apex:pageBlock >
</apex:form >
</apex:page >
The following class is the controller for the page markup above: public class theController {
String searchText;
List<Lead> results; public String getSearchText() { return searchText;
} public void setSearchText( String s) { searchText = s;
} public List<Lead> getResults() { return results;
}
93
Custom Controllers and Controller Extensions Controller Methods public PageReference doSearch() { results = (List<Lead>)[FIND :searchText RETURNING Lead(Name, Email, Phone)][0]; return null ;
}
}
While a getter method is always required to access values from a controller, it’s not always necessary to include a setter method to pass values into a controller. If a Visualforce component is bound to an sObject that is stored in a controller, the sObject's fields are automatically set if changed by the user, as long as the sObject is saved or updated by a corresponding action method. An example of this behavior
is shown in the sample page in Building a Custom Controller
on page 87.
Setter methods must always be named set
Variable
.
Important: It’s a best practice for setter methods to be idempotent, that is, to not have side effects. For example, don’t increment a variable, write a log message, or add a new record to the database. Visualforce doesn’t define the order in which setter methods are called, or how many times they might be called in the course of processing a request. Design your setter methods to produce the same outcome, whether they are called once or multiple times for a single page request.
Getting and Setting Data with a Custom Extension or Controller
There is no guaranteed order in which Apex methods and variables are processed by a controller extension or custom controller. Therefore, do not allow controller and extension classes to rely on another method being run, call that method directly. This applies specifically to setting variables and accessing data from the database.
For example, in the following custom controller, the first method, getContactMethod1
, always returns the correct value because it doesn’t assume that the contact variable c
already exists. The second method, getContactMethod2
, however, sometimes returns the correct value, but not every time if c
hasn’t yet been set.
public class conVsBad {
Contact c; public Contact getContactMethod1() { if (c == null ) c = [SELECT Id, Name FROM Contact LIMIT 1]; return c;
} public Contact getContactMethod2() { return c;
}
}
The following custom controller has the exact same methods. However, getContactMethod2
calls contactMethod1
, so the variable c
is always set, and always contains the correct value when returned.
public class conVsGood {
Contact c; public Contact getContactMethod1() { if (c == null ) c = [SELECT Id, Name FROM Contact LIMIT 1]; return c;
} public Contact getContactMethod2() { return getContactMethod1();
94
Custom Controllers and Controller Extensions Controller Class Security
}
}
The following markup shows two pages that call these controllers. The Visualforce markup is identical, only the controller name is changed:
<apex:page controller= "conVsGood" > getContactMethod2(): {!contactMethod2.name} <br/ > getContactMethod1(): {!contactMethod1.name}
</apex:page >
<apex:page controller= "conVsBad" > getContactMethod2(): {!contactMethod2.name} <br/ > getContactMethod1(): {!contactMethod1.name}
</apex:page >
Controller Class Security
Like other Apex classes, you can specify whether a user can execute methods in a custom controller or controller extension class based on the user's profile.
Note: If you’ve installed a managed package in your org, you can set security only for the Apex classes in the package that are declared as global
or for classes that contain methods declared as webService
.
If users have the “Author Apex” permission, they can access all Apex classes in the associated organization, regardless of the security settings for individual classes.
Permission for an Apex class is checked only at the top level. For example, if class A calls class B, and a user profile has access only to class A but not class B, the user can still execute the code in class A. Likewise, if a Visualforce page uses a custom component with an associated controller, security is only checked for the controller associated with the page. The controller associated with the custom component executes regardless of permissions.
To set Apex class security from the class list page:
1. From Setup, enter
Apex Classes
in the
Quick Find
box, then select Apex Classes.
2. Next to the name of the class that you want to restrict, click Security.
3. Select the profiles that you want to enable from the Available Profiles list and click Add, or select the profiles that you want to disable from the Enabled Profiles list and click Remove.
4. Click Save.
To set Apex class security from the class detail page:
1. From Setup, enter
Apex Classes
in the
Quick Find
box, then select Apex Classes.
2. Click the name of the class that you want to restrict.
3. Click Security.
4. Select the profiles that you want to enable from the Available Profiles list and click Add, or select the profiles that you want to disable from the Enabled Profiles list and click Remove.
5. Click Save.
SEE ALSO:
Security Tips for Apex and Visualforce Development
95
Custom Controllers and Controller Extensions Working with Large Sets of Data
Working with Large Sets of Data
Visualforce custom controllers and controller extensions are subject to Apex governor limits. For more information about governor limits, see
Execution Governors and Limits
on page 709. Additionally, Visualforce iteration components, such as
<apex:pageBlockTable > and
<apex:repeat >
, are limited to a maximum of 1,000 items in the collection they iterate over.
Sometimes your Visualforce pages may need to work with or display larger sets of data, but not need to make modifications to that data; for example, if you are providing custom reporting and analytics. Visualforce offers developers a “read-only mode”, which relaxes the limit on the number of rows which can be queried in one request, and increases the limit on the number of collection items which can be iterated over within the page.
You can specify read-only mode either for an entire page or, with certain limitations, on individual components or methods.
Note: You can only iterate over large sets of data if you specify read-only mode for the entire page.
SEE ALSO:
Setting Read-Only Mode for an Entire Page
Setting Read-Only Mode for Controller Methods
Setting Read-Only Mode for an Entire Page
To enable read-only mode for an entire page, set the readOnly
attribute on the
<apex:page >
component to true
.
For example, here is a simple page that will be processed in read-only mode:
<apex:page controller= "SummaryStatsController" readOnly= "true" >
<p >Here is a statistic: {!veryLargeSummaryStat} </p >
</apex:page >
The controller for this page is also simple, but illustrates how you can calculate summary statistics for display on a page: public class SummaryStatsController { public Integer getVeryLargeSummaryStat() {
Integer closedOpportunityStats =
[SELECT COUNT() FROM Opportunity WHERE Opportunity.IsClosed = true ]; return closedOpportunityStats;
}
}
Normally, queries for a single Visualforce page request may not retrieve more than 50,000 rows. In read-only mode, this limit is relaxed to allow querying up to 1,000,000 rows.
In addition to querying many more rows, the readOnly
attribute also increases the maximum number of items in a collection that can be iterated over using components such as
<apex:dataTable >
,
<apex:dataList >
, and
<apex:repeat >
. This limit increased from 1,000 items to 10,000. Here is a simple controller and page demonstrating this: public class MerchandiseController { public List<Merchandise__c> getAllMerchandise() {
List<Merchandise__c> theMerchandise =
[SELECT Name, Price__c FROM Merchandise__c LIMIT 10000]; return (theMerchandise);
96
Custom Controllers and Controller Extensions Setting Read-Only Mode for Controller Methods
}
}
<apex:page controller= "MerchandiseController" readOnly= "true" >
<p >Here is all the merchandise we have: </p >
<apex:dataTable value= "{!AllMerchandise}" var= "product" >
<apex:column >
<apex:facet name= "header" >Product </apex:facet >
<apex:outputText value= "{!product.Name}" />
</apex:column >
<apex:column >
<apex:facet name= "header" >Price </apex:facet >
<apex:outputText value= "{!product.Price__c}" />
</apex:column >
</apex:dataTable >
</apex:page >
While Visualforce pages that use read-only mode for the entire page can’t use data manipulation language (DML) operations, they can call getter, setter, and action methods which affect form and other user interface elements on the page, make additional read-only queries, and so on.
Setting Read-Only Mode for Controller Methods
Visualforce controller methods can, with some important limitations, use the Apex
ReadOnly
annotation, even if the page itself isn’t in read-only mode.
Visualforce controller methods with the
@ReadOnly
annotation automatically take advantage of read-only mode. However, restrictions on the
@ReadOnly
annotation means that, for Visualforce controller methods, a read-only method must also have the
@RemoteAction
annotation. The
@RemoteAction
annotation requires that the method be:
•
Either global
or public
•
static
Enabling read-only mode by using the
@ReadOnly
annotation must be done on the top level method call. If the top level method call doesn’t have the
@ReadOnly
annotation, the normal restrictions on maximum queried rows are enforced for the entire request, even if secondary methods are annotated with
@ReadOnly
.
Using the
@ReadOnly
annotation on a controller method allows you to retrieve a larger collection of records as the result of a Visualforce expression. However, it doesn’t increase the maximum number of items in a collection for iteration components. If you want to iterate over larger collections of results, you need to enable read-only mode for the entire page.
SEE ALSO:
Setting Read-Only Mode for an Entire Page
"ReadOnly Annotation" in the Force.com Apex Code Developer's Guide
Considerations for Creating Custom Controllers and Controller
Extensions
Note the following considerations when creating controller extensions and custom controllers:
97
Custom Controllers and Controller Extensions Order of Execution in a Visualforce Page
•
Unless a class has a method defined as webService
, custom extension and controller classes and methods are generally defined as public
. If a class includes a web service method, it must be defined as global
.
•
Use sets, maps, or lists when returning data from the database. This makes your code more efficient because the code makes fewer trips to the database.
•
The Apex governor limits for Visualforce controller extensions and custom controllers are the same as the limits for anonymous block or WSDL methods. For more information about governor limits, see
Execution Governors and Limits
in the Appendix.
•
If you are building a custom controller or controller extension, be careful that you do not inadvertently expose sensitive data that would normally be hidden from users. Consider using the with sharing
keywords on class definitions to enforce permissions.
Also be careful using Web services, which are secured as top-level entry points by the profile, but execute in the system context once they are initiated.
•
Custom Extension or Controller on page 94.
•
You can't use data manipulation language (DML) operations in a “getxxx” method in a controller. For example, if your controller had a getName
method, you could not use insert
or update
in the method to create an object.
•
You can't use data manipulation language (DML) operations in a constructor method in a controller.
•
You can't use the
@future
annotation in a “getxxx” or “setxxx” method in a controller, or in the constructor for a controller.
•
Primitive Apex data types such as String or Integer are passed by value to the component's controller.
•
Non-primitive Apex data types such as lists and sObjects are passed by reference to component's controller. This means that if component's controller changes the name of an account, the changes are available in page's controller.
•
If your org uses person accounts
–
When referencing an account record's name
field with a custom controller using the
<apex:inputField >
component you must specify isPersonAccount
in your query.
–
If you create a new account and set name
, the record will be a business account. If you create a new account and set lastname
, it will be a person account.
–
As a best practice, create a custom name formula field that will render properly for both person accounts and business accounts, then use that field instead of the standard field in your Visualforce pages.
–
If you plan on including your Visualforce page in a Force.com AppExchange package, in your controller or controller extension, you cannot explicitly reference fields that exist only in a person account.
Order of Execution in a Visualforce Page
When a user views a Visualforce page, instances of the controller, extensions, and components associated with the page are created by the server. The order in which these elements are executed can affect how the page is displayed to the user.
To fully understand the order of execution of elements on a Visualforce page, you must first understand the page's lifecycle–that is, how the page is created and destroyed during the course of a user session. The lifecycle of a page is determined not just by the content of the page, but also by how the page was requested. There are two types of Visualforce page requests:
•
A get request is an initial request for a page either made when a user enters an URL or when a link or button is clicked that takes the user to a new page.
•
A postback request is made when user interaction requires a page update, such as when a user clicks on a Save button and triggers a save action.
For specific details of the two types of requests, examples illustrating the lifecycle of a page, and tips on how to handle execution order when writing your own custom controllers and controller extensions, see:
•
Order of Execution for Visualforce Page Get Requests
98
Custom Controllers and Controller Extensions Order of Execution for Visualforce Page Get Requests
•
Order of Execution for Visualforce Page Postback Requests
•
Examples of Visualforce Page Execution Order
Note: The maximum response size from a Visualforce page request must be below 15 MB.
Order of Execution for Visualforce Page Get Requests
A get request is an initial request for a page either made when a user enters an URL or when a link or button is clicked that takes the user to a new page. The following diagram shows how a Visualforce page interacts with a controller extension or a custom controller class during a get request:
99
Custom Controllers and Controller Extensions Order of Execution for Visualforce Page Get Requests
In the diagram above the user initially requests a page, either by entering a URL or clicking a link or button. This initial page request is called the get request.
1. The constructor methods on the associated custom controller or controller extension classes are called, instantiating the controller objects.
2. If the page contains any custom components, they are created and the constructor methods on any associated custom controllers or controller extensions are executed. If attributes are set on the custom component using expressions, the expressions are evaluated after the constructors are evaluated.
100
Custom Controllers and Controller Extensions Order of Execution for Visualforce Page Postback Requests
3. The page then executes any assignTo
attributes on any custom components on the page. After the assignTo
methods are executed, expressions are evaluated, the action
attribute on the
<apex:page >
component is evaluated, and all other method calls, such as getting or setting a property value, are made.
4. If the page contains an
<apex:form >
component, all of the information necessary to maintain the state of the database between page requests is saved as an encrypted view state. The view state is updated whenever the page is updated.
5. The resulting HTML is sent to the browser. If there are any client-side technologies on the page, such as JavaScript, the browser executes them.
As the user interacts with the page, the page contacts the controller objects as required to execute action, getter, and setter methods.
Once a new get request is made by the user, the view state and controller objects are deleted.
Note: If the user is redirected to a page that uses the same controller and the same or a proper subset of controller extensions, a postback request is made. When a postback request is made, the view state is maintained.
If the user interaction requires a page update, such as when the user clicks a Save button that triggers a save action, a postback request
For a specific example of a get request, see
Examples of Visualforce Page Execution Order
on page 103.
Order of Execution for Visualforce Page Postback Requests
A postback request is made when user interaction requires a page update, such as when a user clicks on a Save button and triggers a save action. The following diagram shows how a Visualforce page interacts with a controller extension or a custom controller class during a postback request:
101
Custom Controllers and Controller Extensions Order of Execution for Visualforce Page Postback Requests
1. During a postback request, the view state is decoded and used as the basis for updating the values on the page.
Note:
A component with the immediate
attribute set to true
bypasses this phase of the request. In other words, the action executes, but no validation is performed on the inputs and no data changes on the page.
2. After the view state is decoded, expressions are evaluated and set methods on the controller and any controller extensions, including set methods in controllers defined for custom components, are executed.
These method calls do not update the data unless all methods are executed successfully. For example, if one of the methods updates a property and the update is not valid due to validation rules or an incorrect data type, the data is not updated and the page redisplays with the appropriate error messages.
102
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
3. The action that triggered the postback request is executed. If that action completes successfully, the data is updated. If the postback request returns the user to the same page, the view state is updated.
Note: The action
attribute on the
<apex:page >
component is not evaluated during a postback request. It is only evaluated during a get request.
4. The resulting HTML is sent to the browser.
If the postback request indicates a page redirect and the redirect is to a page that uses the same controller and a proper subset of controller extensions of the originating page, a postback request is executed for that page. Otherwise, a get request is executed for the page. If the postback request contains an
<apex:form >
component, only the ID query parameter on a postback request is returned.
Tip: You can use the setRedirect
attribute on a pageReference
to control whether a postback or get request is executed. If setRedirect
is set to true, a get request is executed. Setting it to false does not ignore the restriction that a postback request will be executed if and only if the target uses the same controller and a proper subset of extensions. If setRedirect
is set to false, and the target does not meet those requirements, a get request will be made.
Once the user is redirected to another page, the view state and controller objects are deleted.
Examples of Visualforce Page Execution Order
The following examples illustrate the lifecycle of a Visualforce page as a user interacts with it. The page used in the examples is designed to show information about an account, the value of the variables on the page, and allows the user to edit details of the account if the key value is set to anything except false.
To set up the Visualforce page for the examples:
1. Create a controller for a custom component called componentController
: public class componentController { public String selectedValue { get; set { editMode = (value != null );
// Side effect here - don't do this!
selectedValue = value;
}
} public Boolean editMode {get; private set;}
}
2. Create a custom component called editMode
:
<apex:component controller= "componentController" >
<apex:attribute name= "value" type= "String" description= "Sample component." assignTo= "{!selectedValue}" />
<p >
Value = {!value} <br/ > selectedValue = {!selectedValue} <br/ >
EditMode = {!EditMode}
</p >
</apex:component >
103
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
3. Create a custom controller called myController
: public with sharing class myController { private final Account account; public myController() { account = [select id, name, site, NumberOfEmployees, Industry from Account where id = :ApexPages.currentPage().getParameters().get( 'id' )];
} public Account getAccount() { return account;
} public PageReference save() { update account; return null ;
} public PageReference cancel() { return null ;
}
}
4. Create a controller extension called lifecycle
: public with sharing class lifecycle { private final Account acct;
Integer EmpAdd; public lifecycle(myController controller) { this .acct = (Account)controller.getAccount();
} public String getGreeting() { return acct.name + ' Current Information' ;
} public void resetEmp() { acct.numberofemployees = 10; update acct;
}
}
5. Create a page called setEmps
:
<apex:page controller= "myController" tabStyle= "Account" extensions= "lifecycle" action= "{!resetEmp}" >
<apex:messages />
<apex:pageBlock title= "{!greeting}" >
<apex:outputLabel value= "{!$ObjectType.account.fields.Name.label}: " for= "acctName" />
104
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
<apex:outputField value= "{!account.name}" id= "acctName" />
<br/ >
<apex:outputLabel value= "{!$ObjectType.account.fields.NumberOfEmployees.label}: " for= "emps" />
<apex:outputField value= "{!account.NumberOfEmployees}" id= "emps" />
<br/ >
</apex:pageBlock >
<apex:pageBlock title= "Variable values" >
<c:editMode value= "{!$CurrentPage.parameters.key}" />
</apex:pageBlock >
<apex:form rendered= "{!$CurrentPage.parameters.key = 'true'}" >
<apex:pageBlock title= "Update the Account" id= "thePageBlock" >
<apex:pageBlockSection columns= "1" >
<apex:inputField id= "aName" value= "{!account.name}" />
<apex:inputField value= "{!account.NumberOfEmployees}" />
<apex:pageBlockSectionItem >
<apex:outputLabel value= "{!$ObjectType.account.fields.Industry.label}" for= "acctIndustry" />
<apex:actionRegion >
<apex:inputField value= "{!account.Industry}" id= "acctIndustry" >
<apex:actionSupport event= "onchange" rerender= "thePageBlock" status= "status" />
</apex:inputField >
</apex:actionRegion >
</apex:pageBlockSectionItem >
</apex:pageBlockSection >
<apex:pageBlockButtons location= "bottom" >
<apex:commandButton action= "{!save}" value= "Save" />
<apex:commandButton action= "{!cancel}" value= "Cancel" immediate= "true" />
</apex:pageBlockButtons >
</apex:pageBlock >
</apex:form >
</apex:page >
Get Request Example One
For the first example, visit the setEmps
page using a URL of the form https://Salesforce_instance/apex/setEmps?id=recordId
, where
Salesforce_instance
is the name of your instance (for example, na1
) and
recordID
is the ID of an account record in your organization (for example,
001D000000IRt53
). You'll see a page with content similar to the following:
105
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
Let's trace the lifecycle to see why the page displays what it does. Since you've requested the page directly by entering a URL, this page is the result of a get request, not a postback request.
1. The first thing that happens in a get request is that constructor methods on the custom controller and controller extension are called.
The myController
method is the constructor on the controller and the lifecycle
method is the constructor on the extension. Those are executed and the two objects now exist. The controller now has a variable, called account
, that is the result of a query that uses the id
parameter from the URL, to identify which account object to query. The extension now has a variable, called acct
, that is created by calling the getAccount
method on the controller. The getAccount
method has no side-effects.
2. The next step in a get request is to create the custom components and execute constructor methods on associated controllers or controller extensions. The page includes one custom component:
<c:editMode value= "{!$CurrentPage.parameters.key}" />
This custom component has an associated controller, but the controller has no explicit constructor. As with all Apex objects without explicit constructors, the object is created using an implicit, no-argument, public constructor. As part of creating the custom component, the value attribute on the custom component is set. In this case, it is equal to the result of the expression
{!$CurrentPage.parameters.key}
. Since we did not specify the key
attribute in the URL, value
is set to null.
3. After custom components are created, all assignTo
attributes on those custom components are executed. An assignTo attribute is a setter method that assigns the value of this attribute to a class variable in the associated custom component controller.
The editMode
custom component does have an assignTo
method, so it is executed. The assignTo
method sets selectedValue
on the attribute to the value
attribute. The value
attribute is set to null, so selectedValue
is set to null.
4. The next step in a get request is evaluation of the action
attribute on the
<apex:page >
component , expressions, and the required getter and setter methods. Although we'll step through these below, remember that the order of these evaluations is indeterminate and may be different than the following:
•
The
<apex:page >
component has an action
attribute which calls the resetEmp
method on the extension. That method sets the numberofemployees
field on the acct
object to 10.
•
There are several expressions that evaluate on the page. Let's focus on three:
–
<apex:pageBlock title= "{!greeting}" >
The title
attribute on
<apex:pageblock >
calls the getter method on the lifecycle extension getGreeting
.
This is rendered on the page as “Global Media Current Information.”
–
<apex:form rendered= "{!$CurrentPage.parameters.key
= 'true' } ">
The rendered
attribute on
<apex:form >
is set based on the value of the key
parameter. We did not set key
when calling the page, so the form is not rendered.
–
Value = {!value} <br/ > selectedValue = {!selectedValue} <br/ > EditMode =
{!EditMode}
This expression occurs in the custom component. We've already discussed that value
and selectedValue
are set to null, however, the value of
EditMode
is not yet known.
EditMode
is a boolean variable on the componentController
. It is set based on the whether value
is equal to null: set { selectedValue = value;
// Side effect here - don't do this!
editMode = (value != null );
}
106
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
Since value
is null,
EditMode
is set to false
. Note, however, that there is a side-effect in the setter method for
EditMode
. As part of setting editMode
, we also set selectedValue
to value
. Since value
is null, this doesn't change anything, but this behavior has an impact in a later example.
•
The other expressions and methods are evaluated in a similar manner.
5. Since the
<apex:form >
component isn't rendered, the view state isn't created.
6. The last step in the get request is to send the HTML to the browser, which renders the HTML.
Get Request Example Two
For the second example, visit the setEmps
page using a URL of the form https://Salesforce_instance/apex/setEmps?id=recordId&key=false
, where
Salesforce_instance
is the name of your instance (for example, na1
) and
recordID
is the ID of an account record in your organization (for example,
001D000000IRt53
). Unlike the first example, this example includes a second parameter, key=false
. You'll see a page with content similar to the following:
Let's trace the lifecycle again. This page is also the result of a get request:
1. The first thing that happens in a get request is that constructor methods on the custom controller and controller extension are called.
The myController
method is the constructor on the controller and the lifecycle
method is the constructor on the extension. These are executed and the two objects now exist. The controller now has a variable, called account
, that is the result of a query that uses the id
parameter from the URL to identify which account record to query. The extension now has a variable, called acct
, that is created by calling the getAccount
method on the controller.
2. The next step in a get request is to create the custom components and execute constructor methods on associated controllers or controller extensions. The page includes one custom component:
<c:editMode value= "{!$CurrentPage.parameters.key}" />
This custom component has an associated controller without a constructor, so the controller object is created using an implicit, no-argument, public constructor. As part of creating the custom component, the value
attribute on the custom component is set. In this case, it is equal to the result of the expression
{!$CurrentPage.parameters.key}
. We specified the key attribute as false, so value
is set to false.
3. After custom components are created, all assignTo
attributes on those custom components are executed. The assignTo method sets selectedValue
on the attribute to the value
attribute. The value
attribute is set to false, so selectedValue is set to false.
4. The next step in a get request is evaluation of the action
attribute on the
<apex:page >
component , expressions, and the required getter and setter methods. Although we'll step through these below, remember that the order of these evaluations is indeterminate and may be different than the following:
•
The
<apex:page >
component has an action
attribute which calls the resetEmp
method on the extension. That method sets the numberofemployees
field on the acct
object to 10.
107
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
•
Of the expressions on the page, let's see how our chosen three are evaluated:
<apex:pageBlock title= "{!greeting}" >
The title
attribute on
<apex:pageblock >
calls the getter method on the lifecycle extension getGreeting
. It is rendered on the page as “Global Media Current Information.”
<apex:form rendered= "{!$CurrentPage.parameters.key
= 'true' } ">
The rendered attribute on
<apex:form >
is set based on the value of the key
parameter. We set key
to false
when calling the page, so the form is not rendered.
Value = {!value} <br/ > selectedValue = {!selectedValue} <br/ > EditMode = {!EditMode}
This expression occurs in the custom component. Since value
is not null,
EditMode
is set to true
. At this point, selectedValue
is set to null. Remember, however, that the setter method for
EditMode
has a side-effect. In this case, the side-effect sets selectedValue
to the value
attribute on the custom component. Since value
is set to false
, selectedValue
is set to false. This illustrates why you should not use side-effects in your methods. If the evaluation order were different, and the value for selectedValue
were determined before the setter for
EditMode was evaluated, selectedValue
would still be null. Execution order is not guaranteed, and the result for selectedValue
could change the next time this page is visited.
Warning: Do not use side-effects in your getters or setters!
5. Since the
<apex:form >
component isn't rendered, the view state isn't created
6. The last step in the get request is to send the HTML to the browser, which renders the HTML.
Get Request Example Three
For the third example, visit the setEmps
page using a URL of the form https://Salesforce_instance/apex/setEmps?id=recordId&key=true
, where
Salesforce_instance
is the name of your instance (for example, na1
) and
recordID
is the ID of an account record in your organization (for example,
001D000000IRt53
). Unlike the second example, this example sets key=true
. You'll see a page with content similar to the following:
Let's trace the get request lifecycle one more time:
1. The first thing that happens in a get request is that constructor methods on the custom controller and controller extension are called.
The myController
method is the constructor on the controller and the lifecycle
method is the constructor on the extension. These are executed and the two objects now exist. The controller now has a variable, called account
, that is the result of a query that uses the id
parameter from the URL to identify which account record to query. The extension now has a variable, called acct
, that is created by calling the getAccount
method on the controller.
108
Custom Controllers and Controller Extensions Examples of Visualforce Page Execution Order
2. The next step in a get request is to create the custom components and execute constructor methods on associated controllers or controller extensions. The page includes one custom component:
<c:editMode value= "{!$CurrentPage.parameters.key}" />
This custom component has an associated controller without a constructor, so the controller object is created using an implicit, no-argument, public constructor. As part of creating the custom component, the value
attribute on the custom component is set. In this case, it is equal to the result of the expression
{!$CurrentPage.parameters.key}
. We specified the key attribute as true, so value
is set to true.
3. After custom components are created, all assignTo
attributes on those custom components are executed. The assignTo method sets selectedValue
on the attribute to the value
attribute. The value
attribute is set to true, so selectedValue is set to true.
4. The next step in a get request is evaluation of the action
attribute on the
<apex:page >
component, expressions, and the required getter and setter methods. Although we'll step through these below, remember that the order of these evaluations is indeterminate and may be different than the following:
•
The
<apex:page >
component has an action
attribute which calls the resetEmp
method on the extension. That method sets the numberofemployees
field on the acct
object to 10.
•
Of the expressions on the page, let's see how our chosen three are evaluated:
<apex:pageBlock title= "{!greeting}" >
The title
attribute on
<apex:pageblock >
calls the getter method on the lifecycle extension getGreeting
. It is rendered on the page as “Global Media Current Information.”
<apex:form rendered= "{!$CurrentPage.parameters.key
= 'true' } ">
The rendered
attribute on
<apex:form >
is set based on the value of the key
parameter. We set key
to true when calling the page, so the form is rendered.
Value = {!value} <br/ > selectedValue = {!selectedValue} <br/ > EditMode = {!EditMode}
This expression occurs in the custom component. Since value
is not null,
EditMode
is set to true
. As in the previous example, selectedValue
is set to null. The side-effect in the setter method for
EditMode
sets selectedValue to true
.
5. Since the
<apex:form >
component is rendered, the view state is created.
6. The last step in the get request is to send the HTML to the browser, which renders the HTML.
Postback Request Example
Unlike the first two examples, the third example rendered a final page with editable fields clickable buttons. To understand how a postback request works, use the final page in Example 3 to change the account name to “Pan Galactic Media,” the employee count to
42,” and the industry to “Other.” Then click Save. This initiates a postback request:
1. The first thing that happens in a postback request is that the view state is decoded. The view state contains all the information required to render the page. If, during the postback request, an operation fails, the view state is used to display the page to the user.
2. Next, all expressions are evaluated and methods on controllers and controller extensions are executed.
Of the expressions on the page, let's see how our chosen three are evaluated:
<apex:pageBlock title= "{!greeting}" >
The title
attribute on
<apex:pageblock >
calls the getter method on the lifecycle extension getGreeting
. In our edit, we changed the value of the Account name. Thus, the value of greeting
changes to “Pan Galactic Media Current
Information.”
109
Custom Controllers and Controller Extensions Testing Custom Controllers and Controller Extensions
<apex:form rendered= "{!$CurrentPage.parameters.key
= 'true' } ">
The rendered
attribute on
<apex:form >
is set based on the value of the key
parameter. We have not changed the key
parameter, so the value in the view state is used. Since the value was true when the view state was created, it is still true and the form is rendered.
Value = {!value} <br/ > selectedValue = {!selectedValue} <br/ > EditMode = {!EditMode}
We have not changed any of these values, so, for each expression, the value in the view state is used.
3. Lastly, the save action, the action that triggered the postback request, is evaluated. The save action is the following method on the controller: public PageReference save() { update account; return null ;
}
This method updates the record with the new data. If this method fails, which it might do if the user does not have permission to update the record, or if there are validation rules that are triggered by the change, the page is displayed along with error messages describing the error. The values the user entered are not lost. They remain as they were when the user clicked the Save button.
Assuming there are no errors, the data on the object is updated, the view state is updated, and, since the action that triggered the postback did not include a page redirect, the view state is updated. The resulting HTML is sent to the browser:
SEE ALSO:
Using the Development Mode Footer
Testing Custom Controllers and Controller Extensions
Controller extensions and custom controllers, like all Apex scripts, should be covered by unit tests. Unit tests are class methods that verify whether a particular piece of code is working properly. Unit test methods take no arguments, commit no data to the database, and are flagged with the testMethod
keyword in the method definition.
When writing unit tests for controller extension and custom controller classes, you can set query parameters that can then be used in the tests. For example, the following custom controller and markup is based on the example from
Controller Methods on page 92, but
110
Custom Controllers and Controller Extensions Testing Custom Controllers and Controller Extensions has been extended to expect the following query parameter in the URL for the page:
?qp=yyyy
. A test method class follows, which exercises the functionality of this page: public class thecontroller { private String firstName; private String lastName; private String company; private String email; private String qp; public thecontroller() { this .qp = ApexPages.currentPage().getParameters().get( 'qp' );
} public String getFirstName() { return this .firstName;
} public void setFirstName( String firstName) { this .firstName = firstName;
} public String getLastName() { return this .lastName;
} public void setLastName( String lastName) { this .lastName = lastName;
} public String getCompany() { return this .company;
} public void setCompany( String company) { this .company = company;
} public String getEmail() { return this .email;
} public void setEmail( String email) { this .email = email;
} public PageReference save() {
PageReference p = null ; if ( this .qp == null || !
'yyyy' .equals( this .qp)) { p = Page.failure; p.getParameters().put( 'error' , 'noParam' );
} else { try {
111
Custom Controllers and Controller Extensions Testing Custom Controllers and Controller Extensions insert newlead;
} catch (Exception e) { p = Page.failure; p.getParameters().put( 'error' , 'noInsert' );
}
Lead newlead = new Lead(LastName= this .lastName,
FirstName= this .firstName,
Company= this .company,
Email= this .email);
} if (p == null ) { p = Page.success;
} p.setRedirect( true ); return p;
}
}
The controller calls two additional pages: a success page and a failure page. The text of those pages is not important for this example.
They merely have to exist.
The following markup uses the controller above:
<apex:page controller= "thecontroller" tabstyle= "lead" >
<apex:pageBlock >
<apex:form >
<h1 >Test page for adding leads </h1 >
<p >This is a test page for adding leads.
</p >
<p >First name: <apex:inputText value= "{!FirstName}" > </apex:inputText > </p >
<p >Last name: <apex:inputText value= "{!LastName}" > </apex:inputText > </p >
<p >Company: <apex:inputText value= "{!Company}" > </apex:inputText > </p >
<p >Email address: <apex:inputText value= "{!Email}" > </apex:inputText > </p >
<apex:commandButton action= "{!save}" value= "Save New Lead" />
</apex:form >
</apex:pageBlock >
</apex:page >
The following class tests the controller:
@isTest public class thecontrollerTests { public static testMethod void testMyController() {
PageReference pageRef = Page.success;
Test.setCurrentPage(pageRef); thecontroller controller = new thecontroller();
String nextPage = controller.save().getUrl();
// Verify that page fails without parameters
System.assertEquals( '/apex/failure?error=noParam' , nextPage);
// Add parameters to page URL
ApexPages.currentPage().getParameters().put( 'qp' , 'yyyy' );
112
Custom Controllers and Controller Extensions Validation Rules and Custom Controllers
// Instantiate a new controller with all parameters in the page controller = new thecontroller(); controller.setLastName( 'lastname' ); controller.setFirstName( 'firstname' ); controller.setCompany( 'acme' ); controller.setEmail( '[email protected]' ); nextPage = controller.save().getUrl();
// Verify that the success page displays
System.assertEquals( '/apex/success' , nextPage);
Lead[] leads = [select id, email from lead where Company = 'acme' ];
System.assertEquals( '[email protected]' , leads[0].email);
}
}
Tip: If you are testing your controller you may see the following error message:
Method does not exist or incorrect signature: Test.setCurrentPage(System.PageReference)
If this message appears, look to see if you have created a class called
Test
. If you have, rename the class.
SEE ALSO:
"Testing Apex" in the Force.com Apex Code Developer's Guide
Validation Rules and Custom Controllers
If a user enters data on a Visualforce page that uses a custom controller, and that data causes a validation rule error, the error can be displayed on the Visualforce page. Like a page that uses a standard controller, if the validation rule error location is a field associated with an
<apex:inputField >
component, the error displays there. If the validation rule error location is set to the top of the page, use the
<apex:messages >
component within the
<apex:page >
to display the error. However, to get the information to the page, the custom controller must catch the exception.
For example, suppose you have the following page:
<apex:page controller= "MyController" tabStyle= "Account" >
<apex:messages/ >
<apex:form >
<apex:pageBlock title= "Hello {!$User.FirstName}!" >
This is your new page for the {!name} controller.
<br/ >
You are viewing the {!account.name} account.
<br/ > <br/ >
Change Account Name: <p > </p >
<apex:inputField value= "{!account.name}" /> <p > </p >
Change Number of Locations:
<apex:inputField value= "{!account.NumberofLocations__c}" id= "Custom_validation" />
<p >(Try entering a non-numeric character here, then hit save.) </p > <br/ > <br/ >
<apex:commandButton action= "{!save}" value= "Save New Account Name" />
</apex:pageBlock >
</apex:form >
</apex:page >
Note:
The ID of a valid account record must be specified as a query parameter in the URL for this page to render. For example, http://na3.salesforce.com/apex/myValidationPage?id=001x000xxx3Jsxb
.
113
Custom Controllers and Controller Extensions Using the transient Keyword
You need to write a custom controller like the following: public class MyController {
Account account; public PageReference save() { try {
} update account; catch (DmlException ex){
ApexPages.addMessages(ex);
} return null ;
} public String getName() { return 'MyController' ;
} public Account getAccount() { if (account == null ) account = [select id, name, numberoflocations__c from Account where id = :ApexPages.currentPage().getParameters().get( 'id' )]; return account;
}
}
When the user saves the page, if a validation error is triggered, the exception is caught and displayed on the page as they are for a standard controller.
Using the
transient
Keyword
Use the transient
keyword to declare instance variables that can't be saved, and shouldn't be transmitted as part of the view state for a Visualforce page. For example:
Transient Integer currentTotal;
You can also use the transient
keyword in Apex classes that are serializable, namely in controllers, controller extensions, or classes that implement the
Batchable
or
Schedulable
interface. In addition, you can use transient
in classes that define the types of fields declared in the serializable classes.
Declaring variables as transient
reduces view state size. A common use case for the transient
keyword is a field on a Visualforce page that is needed only for the duration of a page request, but should not be part of the page's view state and would use too many system resources to be recomputed many times during a request.
Some Apex objects are automatically considered transient, that is, their value does not get saved as part of the page's view state. These objects include the following:
•
PageReferences
•
XmlStream classes
•
Collections automatically marked as transient only if the type of object that they hold is automatically marked as transient, such as a collection of Savepoints
•
Most of the objects generated by system methods, such as
Schema.getGlobalDescribe
.
114
Custom Controllers and Controller Extensions Using the transient Keyword
•
JSONParser
class instances.
Static variables also don't get transmitted through the view state.
The following example contains both a Visualforce page and a custom controller. Clicking the refresh button on the page causes the transient date to be updated because it is being recreated each time the page is refreshed. The non-transient date continues to have its original value, which has been deserialized from the view state, so it remains the same.
<apex:page controller= "ExampleController" >
T1: {!t1} <br/ >
T2: {!t2} <br/ >
<apex:form >
<apex:commandLink value= "refresh" />
</apex:form >
</apex:page > public class ExampleController {
DateTime t1; transient DateTime t2; public String getT1() { if (t1 == null ) t1 = System.now(); return '' + t1;
} public String getT2() { if (t2 == null ) t2 = System.now(); return '' + t2;
}
}
115
Download
Advertisement
Key features
Custom UI Development
Integration with Apex
PDF rendering
AJAX support
Custom components
Standard controller
Custom controller
Controller extension
Frequently asked questions
Visualforce is a framework that allows you to create custom user interfaces for Salesforce applications.
The document does not explicitly state which editions support Visualforce. See Salesforce official documentation for details.
The document explains some aspects of Visualforce architecture.