function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SpaceManSpiffSpaceManSpiff 

Creating an Apex Controller that extends mutiple Standcontrollers

Hello all,

 

I am trying to create a few RemoteAction methods that can be accessed in multiple visualforce pages and Apex triggers to comunicate with a third party system in our company. I want to centralize these methods so all instances can be updated simultaneously.

 

The problem I am running into is that some of the Visualforce pages that I need this class to extend use the Opportunity StandardController and others use the Contact StandardController. Is there anyway that I can have a single Apex class extend across VF pages using the Opportunity and the Contact Standard controllers?

 

Thanks in advance.

 

-Clark

Best Answer chosen by Admin (Salesforce Developers) 
James LoghryJames Loghry

SpaceManSpiff,

 

You have a couple of options...

 

1) Change your opp and con variables to be a single sObject variable.  This will work well if you only need standard fields such as Name on both sObjects. 

 

private final sObject sobj;

 

global ...{

  this.sobj = stdController.getRecord();

}

 

2) Catch the exception when setting the variables

 

global Global_Methods(ApexPages.StandardController stdController){
try{
this.opp = (Opportunity)stdController.getRecord();
}catch(System.TypeException e){
this.con = (Contact)stdController.getRecord();
}
}

 

3) Or you can issue a describe call such as

global Global_Methods(ApexPages.StandardController stdController){

  String prefix = Schema.getGlobalDescribe().get('Opportunity').getDescribe().getKeyPrefix();

  if(((String)stdController.getRecord().Id).startsWith(prefix)){

    opp = (Opportunity)stdController.getRecord();

  }else{

    con = (Contact)stdController.getRecord();

  }

}

 

If you can get away with it, I would just use the first option.

No matter which option you use, though, be sure to handle all the exception scenarios.  Having your main record variable come from two possible sobject types can be difficult to handle. As always, make sure your unit test class thoroughly handles all the cases as well.

 

 

 

 

 

}

All Answers

James LoghryJames Loghry

Sure,  have a look at Visualforce Controller Extensions:

http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_extension.htm

 

Pretty straight forward to use if you havent used them before.

 

If you need to differentiate the record that comes in through the constructor,  you can use some describe magic to cast it into either a Contact or Opportunity.

 

Hope that helps.

SpaceManSpiffSpaceManSpiff

Thanks for the reply James. 

 

Here is the code I have used in the constructor to attempt to distinguish between extending a Contact and an Opportunity to no avail:

 

	private final Opportunity opp;
	private final Contact con;
	
	global Global_Methods(ApexPages.StandardController stdController){
		if ((Opportunity)stdController.getRecord() != null ){
			this.opp = (Opportunity)stdController.getRecord();
		}
		else if ((Contact)stdController.getRecord() != null){
			this.con = (Contact)stdController.getRecord();
		}
	}

 

This is the error I get: Content cannot be displayed: Invalid conversion from runtime type SOBJECT:Contact to SOBJECT:Opportunity.

 

I am relatively new at coding VisualForce so all suggestions are welcome!

James LoghryJames Loghry

SpaceManSpiff,

 

You have a couple of options...

 

1) Change your opp and con variables to be a single sObject variable.  This will work well if you only need standard fields such as Name on both sObjects. 

 

private final sObject sobj;

 

global ...{

  this.sobj = stdController.getRecord();

}

 

2) Catch the exception when setting the variables

 

global Global_Methods(ApexPages.StandardController stdController){
try{
this.opp = (Opportunity)stdController.getRecord();
}catch(System.TypeException e){
this.con = (Contact)stdController.getRecord();
}
}

 

3) Or you can issue a describe call such as

global Global_Methods(ApexPages.StandardController stdController){

  String prefix = Schema.getGlobalDescribe().get('Opportunity').getDescribe().getKeyPrefix();

  if(((String)stdController.getRecord().Id).startsWith(prefix)){

    opp = (Opportunity)stdController.getRecord();

  }else{

    con = (Contact)stdController.getRecord();

  }

}

 

If you can get away with it, I would just use the first option.

No matter which option you use, though, be sure to handle all the exception scenarios.  Having your main record variable come from two possible sobject types can be difficult to handle. As always, make sure your unit test class thoroughly handles all the cases as well.

 

 

 

 

 

}

This was selected as the best answer
SpaceManSpiffSpaceManSpiff

I went with the second solution because the first one didn't work perfectly. 

 

Thank you James! You the Man!