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
TeamFuguTeamFugu 

Problem with object ID's in parameters

I have a page that retrieves an object ID from a parameter list. The problem is that when the object is deployed into a new instance from my sandbox or from one sandbox to another, the Id changes. I'd like to find a way that I can not have to add "magic strings" where I hard code the Id in the Apex code. This becomes painful when deploying because we have to maintain an ever growing list of classes that need to be changed after deployment.

 

I also have a similar problem with some URLs that point to other pages. Is there a repository I can query using the name of the page that will return the Id?

Best Answer chosen by Admin (Salesforce Developers) 
TeamFuguTeamFugu

There are a few ways to do this. From the VisualForce page, using the $Action global merge field, you can do something like {!URLFOR($Action.myObject__c.New)}  to set the value of a parameter for the page submit and it will render the link to the page for creating a new object of type myObject__c. You have to remember that custom objects are assigned a prefix, in the sandbox you are working, in the order they are inserted. There is no way you can guarantee that the prefix will be consistent across sanboxes.

 

In your custom controller, you may use:

Schema.DescribeSObjectResult r = Schema.SObjectType.myObject__c;
String pageRef = r.getKeyPrefix() + '/o';

 to build the string for the landing page for the myObject__c custom object when you don't have a tab created for easy acces. If you want to land on the standard page for the creation of a new instance of that object, replace the 'o' with an 'e'.

 

Very easy once you see how its done.

 

I hope this helps someone else.

 

All Answers

TeamFuguTeamFugu

I think I have this fixed now. Not as efficient as hard coding what I call "magic strings".

 

What follows is a snippet of code I did. It seemed to work OK. One of you may have a much better way but at least this way, I hope, I don't have magic strings that are Id's that have to be checked after deployment.

        Set<String> keys = ApexPages.currentPage().getParameters().keySet();
        if( keys != null && keys.size() > 0 ){
        	for( String s : keys ){
        		if( s.substring(0,3) == 'CF0' ){
        			interfaceID = ApexPages.currentPage().getParameters().get( s + '_lkid' );
        			break;
        		}
        	}
        }

 

Manos SpanoudakisManos Spanoudakis

You can use Custom Settings for this 

TeamFuguTeamFugu

manos, I would agree but I still have the problem of having to find out what that Id is. I see custom settings as a way of doing what we call defines in C/C++ or public static final fields in Java where the value for something doesn't change and so you don't have to riddle code with magic numbers or magic strings. The problem here is that it is a reference to a custom page or tab object that I can't see how to query by name so I wanted some other way to get the Id. If I put object Id's in custom settings, then I still have the problem of having to make changes after deployment, only changing the location the change has to be made and I find this to be very poor design and error prone due to possible data entry errors and omission errors.

Manos SpanoudakisManos Spanoudakis

I think Custom Settings are more like properties in Java because you actually don't need a redeployment / recompile to update values. 

In any case you need to update something so for me the best way is to do it outside your code, and thus the best option is Custom Settings. 

 

I would also like to have the Ids in the Describe method but it's not there :( 

 

TeamFuguTeamFugu

I understand what you're saying about custom settings but the problem I'm trying to address is when this is an object Id that may, or may not, change from deployment from a sandbox, to a testing area, and then to a live deployment. Each step would be error prone to either transposition errors or forgetting to make sure that the object ID that is in the custom settings matches with the object ID as it stands in the deployment.

 

I saw the object Id change when my sandbox was created and so I know I can't guarantee that the object Id will persist from deployment to deployment and having to have someone else remember to discover the Id and remember to change it at each move is HIGHLY error prone and bad practice as far as I'm concerned.

 

It would be great if there were a way to query the system setup for the Id's of custom pages, tabs, and other objects to obtain their Ids. It is my hope that there is such a way and I just haven't run across it yet.

 

Custom settings should be used for values that don't change and not for things that could possibly change from deployment to deployment.

Manos SpanoudakisManos Spanoudakis

To my knowledge there is no way to get this information from Apex...

 

The best approach is to first create All Objects/Fields/Etc in your production and then create Sandboxes. That way you will get same id's. 

I know it's not always possible... 

 

 

TeamFuguTeamFugu

What you say is contrary to what I found. My sandbox didn't exist and was created from another instance. We found that the Id of some of the objects changed in my sandbox from the one that it was created from. This tells me I can't depend on anything being preserved in a deployment.

Manos SpanoudakisManos Spanoudakis

never happened to me so far...

That's why your best option is Custom Settings ;-) 

TeamFuguTeamFugu

Though I somewhat agree about using custom settings, I still don't like using that method for this issue. It is easy to discover from the parameter list and I think that is far less prone to error than having to rely on someone remember to check and change settings at every deployment. Too much potential for error for me.

 

Thanks for the input though.

TeamFuguTeamFugu

There are a few ways to do this. From the VisualForce page, using the $Action global merge field, you can do something like {!URLFOR($Action.myObject__c.New)}  to set the value of a parameter for the page submit and it will render the link to the page for creating a new object of type myObject__c. You have to remember that custom objects are assigned a prefix, in the sandbox you are working, in the order they are inserted. There is no way you can guarantee that the prefix will be consistent across sanboxes.

 

In your custom controller, you may use:

Schema.DescribeSObjectResult r = Schema.SObjectType.myObject__c;
String pageRef = r.getKeyPrefix() + '/o';

 to build the string for the landing page for the myObject__c custom object when you don't have a tab created for easy acces. If you want to land on the standard page for the creation of a new instance of that object, replace the 'o' with an 'e'.

 

Very easy once you see how its done.

 

I hope this helps someone else.

 

This was selected as the best answer