There is a problem with the code in Hack to find field ids – allows a default UI “New” page to be pre-populated related to case sensitivity. The field ids are case sensitive so it is possible (and if your object has many fields likely) that field ids may only differ by case. Such fields are not correctly defaulted in the “New” page.
While specifications like RFC 3986 suggest that query string keys can be assumed to be case sensitive, the PageReference class in Force.com works hard to ensure that query string keys are not case sensitive. These tests illustrate the problem:
@isTest
static void testMap() {
Map<String, String> m = new Map<String, String>();
m.put('00N50000002ldUw', 'abc');
m.put('00N50000002ldUW', '123');
// Assertions are as expected
System.assertEquals('abc', m.get('00N50000002ldUw'));
System.assertEquals('123', m.get('00N50000002ldUW'));
}
@isTest
static void testParameters() {
PageReference p = new PageReference('/');
Map<String, String> m = p.getParameters();
m.put('00N50000002ldUw', 'abc');
m.put('00N50000002ldUW', '123');
// Assertions illustrate that keys that differ by case are not distinguished
System.assertEquals('123', m.get('00N50000002ldUw'));
System.assertEquals('123', m.get('00N50000002ldUW'));
}
There does not appear to be a work-around using PageReference; building the entire URL string manually and then passing it into the constructor doesn’t help, nor does replacing the alphabetic characters with their URL encoded form. The other standard practice of replacing a (case sensitive) 15 digit id with the (case insensitive) 18 character version doesn’t work in this case because the “New” page appears to be doing literal string matching of the ids and so is expecting the 15 character version.
A way of avoiding the PageReference class is to build the URL as a string and then use JavaScript to redirect to the URL. These changes to the code in Hack to find field ids – allows a default UI “New” page to be pre-populated fix the case problem and result in all fields being defaulted. The controller returns a URL string:
private String createUrl() {
String url = '/' + DescribeSObjectResultCache.get(Abc__c.SObjectType).getKeyPrefix()
+ '/e'
+ '?retURL=' + ApexPages.currentPage().getParameters().get('retURL')
+ '&nooverride=1'
;
Map m = createDefaultValues();
for (String key : m.keySet()) {
url += '&' + key + '=' + EncodingUtil.urlEncode(m.get(key), 'UTF-8');
}
return url;
}
public String url {
get {
if (url == null) {
url = createUrl();
}
return url;
}
private set;
}
and the page is rendered but immediately redirects to the URL supplied by the controller:
<apex:page standardController="Abc__c" extensions="AbcNewController" showHeader="false" sidebar="false" standardStylesheets="false">
<script type="text/javascript">
window.onload = function() {
window.location = '{! url }';
}
</script>
</apex:page>
Good to see you solving the problems, and corner cases. We should for sure post the idea to have field id’s available in apex describe information ! If you haven’t posted this as idea, we can post and vote ?
Comment by Abhinav Gupta — February 1, 2012 @ 10:20 am |
Abhinav, Feel free to go ahead and post the idea: it would be a worthwhile improvement if implemented. The hard part is to get Salesforce to prioritise such developer oriented improvements.
Comment by Force 201 — February 1, 2012 @ 10:27 am |
Sure, lets try to get as many votes as we can. Sooner or later if this idea gets implemented life would be easier
Comment by Abhinav Gupta — February 1, 2012 @ 11:34 am
Here is the link to the idea : https://sites.secure.force.com/success/ideaView?id=08730000000gM7mAAE
Comment by Abhinav Gupta — February 1, 2012 @ 12:37 pm