I have had a few occasions where I wanted to invoke Apex Code by clicking a button on a Page Layout. Everywhere I looked, it always said I needed to have the button call an s-Control, which would then invoke Apex Code that’s written as a Web Service. I am doing my best to avoid using s-Controls and figured there had to be a way using Visualforce instead of an s-Control. The key was the action attribute on the <apex:page tag.
Suppose you wanted to add a button on your Opportunity page that automatically did something when you pushed the button. You can’t execute Apex Code directly from a button. You need something in the middle. Let’s try to do it with a Visualforce page instead of an s-Control.
Controller
The controller has the main method in it to be executed. This method returns a PageReference (very important). Note that the method does not need to be a webservice.
public class VFController {
// Constructor - this only really matters if the autoRun function doesn't work right
private final Opportunity o;
public VFController(ApexPages.StandardController stdController) {
this.o = (Opportunity)stdController.getRecord();
}
// Code we will invoke on page load.
public PageReference autoRun() {
String theId = ApexPages.currentPage().getParameters().get('id');
if (theId == null) {
// Display the Visualforce page's content if no Id is passed over
return null;
}
for (Opportunity o:[select id, name, etc from Opportunity where id =:theId]) {
// Do all the dirty work we need the code to do
}
// Redirect the user back to the original page
PageReference pageRef = new PageReference('/' + theId);
pageRef.setRedirect(true);
return pageRef;
}
}
Visualforce
The Visualforce page is very simple. You really don’t need anything in there except the action parameter invokes code (the autoRun method) that runs before the page is initialized. That method returns a Page Reference that redirects the user back to the original page.
<apex:page standardController="Opportunity"
extensions="VFController"
action="{!autoRun}"
>
<apex:sectionHeader title="Auto-Running Apex Code"/>
<apex:outputPanel >
You tried calling Apex Code from a button. If you see this page, something went wrong. You should have
been redirected back to the record you clicked the button from.
</apex:outputPanel>
</apex:page>
Custom Button
All we need now is a custom Opportunity button. Because we used the Opportunity standard controller in the Visualforce page, we can simply have the button point to a the page we created.
Add that button to your Page Layout and all should work swimmingly.