Force.com Tip: ‘New’ Button Override to Assign VisualForce Page to Specific Record Type Using Native Apex Code

You’ve probably come across this before…you need to create a custom VisualForce page for a specific Record Type, but overriding the ‘New’ or ‘Edit’ button seems to be an all-or-nothing proposition (i.e. you can do a single VisualForce page and embed the Page Layout using Apex:Detail, but you can’t mix custom pages with standard Page Layouts). We came across this recently at Delivered Innovation, and we want to share our solution with the community. This specific example involves the Salesforce Case object, but can be applied to any Standard or Custom Object.

Use Case: Client has multiple call centers supporting various product lines; support team ‘A’ requires a custom Wizard to rapidly search for and collect details for the Case record that the standard Salesforce search interface cannot provide.

Solution: While you can assign a specific Page Layout to a specific Record Type and embed VisualForce pages in the object Detail view, currently salesforce.com does not support embedded VisualForce Pages in the Edit view of a Page Layout; likewise, salesforce.com does not support custom VisualForce pages for specific Record Types.  The solution is to “intercept” the command to create a new record in an Object before Salesforce processes it, and this is accomplished with a 1-line VisualForce page and a StandardController extension that pulls and analyzes certain URL parameters to enhance the out-of-the-box process routing capabilities of Salesforce.

The VisualForce Page code:

<apex:page standardController="Case" extensions="caseRedirect" tabStyle="Case" showheader="true" action="{!redirect}" />

The Apex controller extension:

public with sharing class caseRedirect {

private ApexPages.StandardController controller;
public String retURL {get; set;}
public String saveNewURL {get; set;}
public String rType {get; set;}
public String cancelURL {get; set;}
public String ent {get; set;}
public String confirmationToken {get; set;}
public String accountID {get; set;}
public String contactID {get; set;}

public caseRedirect(ApexPages.StandardController controller) {

	this.controller = controller;

	retURL = ApexPages.currentPage().getParameters().get('retURL');
	rType = ApexPages.currentPage().getParameters().get('RecordType');
	cancelURL = ApexPages.currentPage().getParameters().get('cancelURL');
	ent = ApexPages.currentPage().getParameters().get('ent');
	confirmationToken = ApexPages.currentPage().getParameters().get('_CONFIRMATIONTOKEN');
	saveNewURL = ApexPages.currentPage().getParameters().get('save_new_url');
	accountID = ApexPages.currentPage().getParameters().get('def_account_id');
	contactID = ApexPages.currentPage().getParameters().get('def_contact_id');

}

public PageReference redirect() {

	PageReference returnURL;

	// Redirect if Record Type corresponds to custom VisualForce page

	IF(rType == 'xxxxxxxxxxxxxxx') {

		returnURL = new PageReference('/apex/insert_VF_Page_Here');

	}

	ELSE {

		returnURL = new PageReference('/500/e');

	}

	returnURL.getParameters().put('retURL', retURL);
	returnURL.getParameters().put('RecordType', rType);
	returnURL.getParameters().put('cancelURL', cancelURL);
	returnURL.getParameters().put('ent', ent);
	returnURL.getParameters().put('_CONFIRMATIONTOKEN', confirmationToken);
	returnURL.getParameters().put('save_new_url', saveNewURL);
	returnURL.getParameters().put('nooverride', '1');

	IF (accountID != null){

		returnURL.getParameters().put('def_account_id', accountID);

	}

	IF (contactID != null){

		returnURL.getParameters().put('def_contact_id', contactID);

	}

	returnURL.setRedirect(true);
	return returnURL;

}

}

Now for the important part – in order for this to work when Salesforce users create new Case records, you need to override the ‘New’ button for the ‘Case’ Standard Object.  This can be accomplished by selecting ‘Setup / Customize / Cases / Buttons and Links / ‘Override’ on ‘New’.  Select ‘VisualForce Page’ for “Content Type,” and then select the VisualForce page you created using your modification of the code above in the “Content Name” dropdown list, and you’re set.  The “Comment” area is optional. Don’t forget to set the security for this VisualForce page to provide the required Profiles with access.

Jeff Douglas has provided another method for achieving automated redirection to VisualForce pages on his blog.  You can find the link here.

Mike Topalovich Salesforce Technical Architect in Chicago
Mike Topalovich - Salesforce Certified Force.com Platform Developer I Mike Topalovich - Salesforce Certified Force.com Platform Developer II Mike Topalovich - Salesforce Certified Force.com Developer Mike Topalovich - Salesforce Certified Force.com Advanced Developer
Mike Topalovich - Salesforce Certified Mobile Solutions Architecture Designer Mike Topalovich - Salesforce Certified Force.com Platform App Builder Mike Topalovich - Salesforce Certified Administrator Mike Topalovich - Salesforce Certified Advanced Administrator
Mike Topalovich
Hi, I’m Mike. I help companies like yours do business in new ways with Salesforce.

I am a freelance Salesforce Developer, Architect, and CTO as well as a part time instructor for Salesforce University.

Connect with me today to discuss how I can become a part of your team on an ongoing retainer basis.
Mike Topalovich on EmailMike Topalovich on FlickrMike Topalovich on LinkedinMike Topalovich on RssMike Topalovich on Twitter

6 Comments

  1. mrBlaQ

    It doesn’t look like this works anymore. Setting a custom override VF page on a button now causes any request to the obj’s “add” URL to forward back to the VF page. If I browse to /a1s/e for my custom object, It forwards me to my /Apex/FooBar page.

    Reply

  2. Keith Larsen

    Hi Mike,

    I’ve implemented you override of my New button but I’m struggling to write a test case. Can you post your test case that goes along with your example?

    Thanks.

    Reply

  3. Dmitriy

    Thank you so mutch for this post!!!

    I needed to prefill some fields on new record after an user clicked on the new button on list view and selected record type.

    So I overrided new button on my custom object tab with NewItem.page (cannot use js nor remove new button from recent items) and added an action for page reference method, but it did not work permanently trying to forward me back to NewItem.page as noted MRBLAQ. But it works after I added url parameter my PageRef.getParameters().put(‘nooverride’, ‘1’);

    Reply

  4. Jeff Berger (@jeffereyberger)

    Hi Mike,
    Great post! This does exactly what I need it to, and I really appreciate you putting this out there for the community. Admittedly I’m not a code guru by any means–is there any chance you could post your test class for this code as well? Thanks so much!

    On a related note: Ideally I want to launch my new object creation from the related list on an Account record and I want to pass the Account Id through the record selection screen and into the visualforce page that is replacing the standard “new” functionality. Is there an easy way to modify this controller to also handle that requirement?
    Thanks!

    Reply

    • Mike Topalovich

      Hi, Jeff. I will take a look to see if I still have this code in a repo.

      To take care of your use case, what you would do is create the custom button for the related list that concatenates a reference to your Visualforce page (e.g. ‘/apex/MyVisualforcePage’) with a URL parameter that contains the accountId (e.g. + ‘?accountId={!fieldNameContainingAccountId}’).

      In the controller, use the getParameters() method to retrieve the accountId URL parameter (e.g. apexpages.currentpage().getparameters().get(‘accountId’) and you can use that when constructing the new sObject.

      Reply

  5. Mark Maslow

    Nice tip.

    But you don’t have to pull off every parameter and put them back individually. You can just iterate through the keys and get the values.

    Here’s my redirect method for a special type of Campaign

    public PageReference redirect() {
    PageReference returnURL;

    // Redirect if Record Type corresponds to custom VisualForce page

    String rType = ApexPages.currentPage().getParameters().get(‘RecordType’);
    IF(rType == eventsTypeId) {
    returnURL = new PageReference(‘/apex/EventCampaignEntry’);
    }

    ELSE {
    returnURL = new PageReference(‘/701/e’);
    }

    parameterMap = ApexPages.currentPage().getParameters();
    for(String param : parameterMap.keySet()) {
    returnURL.getParameters().put(param, parameterMap.get(param));
    }
    returnURL.setRedirect(true);
    return returnURL;

    }

    Reply

Leave a Reply