Error Handling Customization in Visualforce

I am a proponent of developing Visualforce pages that enhance user experience by providing valuable feedback, thereby minimizing user frustration. In certain scenarios, this involves presenting clearer error messages rather than merely displaying system-generated errors.

In this illustration, we aim to construct a custom search page enabling users to query Contacts by supplying a search term. To offer maximum flexibility, we permit searches with wildcard characters. Behind the scenes, we employ the FIND clause in our SOSL query to facilitate this functionality.

Before delving into the development process, it’s crucial to note two considerations. First, the FIND clause mandates a minimum of two characters for the query to execute. Second, when a wildcard is utilized, we must ensure the presence of two non-wildcard characters in addition to the wildcard.

Now that these points are highlighted, we can proceed with constructing the controller logic for the page.

/*
	Created by: Greg Hacic
	Last Update: 31 August 2015 by Greg Hacic
	Questions?: greg@interactiveties.com
	
	Notes:
		- controller for errorHandlingSample.page
*/
public with sharing class errorHandlingSample {
	
	public List<Contact> contactRecords = new List<Contact>(); //list for Contact records
	public String searchError; //variable for housing the error text
	public String searchString {get; set;} //the input provided by the User as they interact with the Visualforce page
	
	//constructor
	public errorHandlingSample() {
		performSearch(); //call the performSearch method
	}
	
	//getter for the searchError variable
	public String getSearchError() {
		return searchError; //return searchError value
	}
	
	//method for searching based upon the search string provided from the user interface
	public void performSearch() {
		contactRecords.clear(); //clear the current list
		searchError = null; //null out the search error string
		if (searchString != '' && searchString != null) { //if searchString is not null
			if (searchString.length() >= 2) { //if searchString has more than 1 character
				if ((searchString.contains('*') || searchString.contains('?')) && searchString.length() < 3) { //if searchString is less than 3 characters long and contains a wildcard value
					searchError = 'Three characters are required when using wildcards in your search.'; //provide an error message so the User may revise their search
				}
			} else { //otherwise, the searchString is less than 2 characters long
				searchError = 'You must include at least two characters in the search string.'; //provide an error message so the User may revise their search
			}
			if (searchError == null) { //if searchError is null
				List<List<sObject>> searchList = [FIND :searchString IN ALL FIELDS RETURNING Contact(AccountId, Account.Name, Id, Email, MobilePhone, Name, Phone, Title ORDER BY LastName)]; //search for all contacts
				List<Contact> listOfFoundContacts = ((List<Contact>)searchList[0]); //cast the search results into a list of Contacts
				for (Contact c : listOfFoundContacts) { //for all Contacts returned in our search
					contactRecords.add(c); //add the Contact to our contactRecords list
				}
			}
		}
	}
	
	//getter for the list of Contacts
	public List<Contact> getContactRecords() {
		return contactRecords;
	}
	
	//getter for the size of the list of Contacts
	public Integer getContactRecordsSize() {
		return contactRecords.size();
	}

}

What you’ll notice first about the above controller is, rather than relying on the system to throw an error, we are using an error string variable (searchError) to denote when we encounter issues for which we are coding. We will use this variable in our Visualforce page and if the value is null we will show a table of records from our search results. When the value is not null we will show an error message instead of table of results. See the code for our page below:

<apex:page controller="errorHandlingSample" docType="html-5.0" showHeader="true" sidebar="true" standardStylesheets="true">
<!--
	Created by: Greg Hacic
	Last Update: 31 August 2015 by Greg Hacic
	Questions?: greg@interactiveties.com
-->
	<apex:sectionHeader title="Search" subtitle="Contacts"></apex:sectionHeader>
	<p>This is a Visualforce example illustrating how to handle errors in a more granular manner. Try searching for <b>g*</b> or <b>g</b> to see the error messaging.</p>
	<apex:pageMessages></apex:pageMessages>
	<apex:form>
		<div style="margin: 25px;">
			Filter: &nbsp;
			<apex:inputText id="searchString" size="25" title="name of company, contact, city, state, zip code" value="{!searchString}"></apex:inputText>&nbsp; <!-- input field -->
			<apex:commandButton action="{!performSearch}" id="runContactSearch" rerender="searchResultsArea" status="requestStatus" value="Search"></apex:commandButton> <!-- search button -->
		</div>
		<apex:actionStatus id="requestStatus"><!-- component that displays the status of an AJAX request -->
			<apex:facet name="start"> <!-- placeholder for content that's rendered when the AJAX request is started -->
				<apex:image url="/img/loading.gif" alt=" Loading... "></apex:image> <!-- a rotating .gif image -->
			</apex:facet>
			<apex:facet name="stop"> <!-- placeholder for content that's rendered when the AJAX request is finished -->
				<apex:outputPanel id="searchResultsArea" layout="block">
					<apex:outputPanel rendered="{!searchError != null}"> <!-- error messaging area rendered whenever the searchError variable is not null -->
						<div class="message errorM2"> <!-- standard styling that Salesforce uses throughout the platform we are just adopting it here -->
							<table border="0" cellpadding="0" cellspacing="0" class="messageTable" style="padding: 0px; margin 0px;">
								<tr valign="top">
									<td><img src="/s.gif" class="msgIcon" title="" /></td> <!-- standard Salesforce warning graphic -->
									<td class="messageCell"><div class="messageText">{!searchError}</div></td> <!-- the place where we render any searchError value from the controller -->
								</tr>
							</table>
						</div>
					</apex:outputPanel>
					<apex:outputPanel rendered="{!AND( NOT( searchError != null), contactRecordsSize < 1 )}"> <!-- informational messaging area rendered when there are no results from the search -->
						<div class="message infoM2"> <!-- standard styling that Salesforce uses throughout the platform we are just adopting it here -->
							<table border="0" cellpadding="0" cellspacing="0" class="messageTable" style="padding: 0px; margin 0px;">
								<tr valign="top">
									<td><img src="/s.gif" class="msgIcon" title="" /></td> <!-- standard Salesforce informational graphic -->
									<td class="messageCell"><div class="messageText">Your search yields no results...</div></td>
								</tr>
							</table>
						</div>
					</apex:outputPanel>
					<apex:pageBlock rendered="{!contactRecordsSize > 0}" title="Results">
						<apex:pageBlockTable cellpadding="2" cellspacing="2" value="{!contactRecords}" var="c" width="100%">
							<apex:column>
								<apex:facet name="header">Name</apex:facet>
								<a href="/{!c.Id}">{!c.Name}</a>
							</apex:column>
							<apex:column value="{!c.Title}" />
							<apex:column value="{!c.AccountId}" />
							<apex:column value="{!c.Email}" />
							<apex:column value="{!c.MobilePhone}" />
							<apex:column value="{!c.Phone}" />
						</apex:pageBlockTable>
					</apex:pageBlock>
				</apex:outputPanel>
			</apex:facet>
		</apex:actionStatus>
	</apex:form>
</apex:page>

Additionally, you might observe the inclusion of the apex:pageMessages tag in our page, serving the purpose of capturing any system errors that may not have been specifically addressed in our code.