Last week, we took a look at a skeletal version of a class implementing the asynchronous aspects of Apex: batch, scheduled and email. While powerful, it’s a corner of Apex developers don’t always have a use case to tread down into. This week, let’s look at something a lot more common: Visualforce controllers – quite possibly the most common use of Apex on the planet.
But Josh, you might ask – how long could such a template be? After all, your basic controller only has one real requirement – and that’s a constructor of some kind. That would just be too easy, of course. The idea behind these templates is to give developers a starting point for what these classes can really execute, and there are a lot of different things that you can execute on with a Visualforce page. So while this template is going to be light on actual code, in agreement with the “no functionality” concept behind the templates – it is going to be full of commented code examples as quick reminders of how to accomplish commonly used functionality on a controller (or extension).
So let’s crack on some commented code. The whole class is up on github if you’d like to follow along at home. In the nofunc version, most of the code you’ll see here will be commented out – but I’ve left the comment blocks to the wayside in these examples for better code highlighting.
Basic enough right? Except that it is good to remember that how you set your variables in Apex has a direct impact on your Visualforce page, assuming you are going to have an apex:form component in use. That’s because public variables will appear in the viewstate, which increases the size and time of your data transport back to the controller, while variables which are transient or static do not.
Also note that the class itself is using the with sharing keyword, which will force Apex to obey the sharing rules of the current user. Most controllers should be using that keyword.
Constructors on a Visualforce page are going to be mostly responsible for defining the initial state of the data that the user will see. When I’m first writing code like that, it is tempting to just toss out some of SOQL statements, fill some arrays and then be along my way. However, I usually find that won’t be sufficient down the road. This is because I’m forgetting the following frequently used scenarios:
- Detecting incoming query parameters
- Validating incoming query parameters (important for blocking injection attacks)
- Handling potential DML errors
- Notifying the user of custom error scenarios via Apex Messages.
So here is a constructor with that set of examples:
Note that last comment – it’s a helpful reminder. You can’t perform DML within the constructor of a Visualforce page. You can tie DML to a method referred to the action attribute of your page component if you need to perform DML when the page first loads.
Another habit I have gotten into is always creating two constructors – one for a controller, and one for an extension. I might never use the second controller, but if I want to port this same logic over to a page with a StandardController set, it allows me to easily keep everything to one class:
Now we just need to let our controller actually do something. I generally think of how Visualforce and Apex will interact in three main types:
- A method which will respond to changes via apex:param and return a PageReference
- A method which will be send a specific data point back as a getter
Here are three methods which correspond to that:
Now, there is one other kind of transaction which is less commonplace these days: cookies. Once the end all and be all of controlling a session, client-side cookies have taken something of a backseat to server-side data management. Heck, when I first starting with Apex it wasn’t even an option – but we do have the ability now, and the utilization looks like this:
You can’t escape unit testing, not if you want your code to eventually make it into production. Testing Visualforce controllers is often very similar to testing normal Apex code, except when the page interaction itself is in question. This usually materializes in the form of query parameters which aren’t normally set when constructing just the Apex class. To solve this, Test has a method to set the current page being seen by the unit test context:
And there you have – an example of the most common use cases on a Visualforce controller. You can follow the whole nofunc project on Github as it unfolds, and either start your own branch to suggest changes and updates – or as always leave us a note in the comment box below, or catch me on twitter @joshbirk. Happy coding, gang.