I'm trying to use the metadata api to do related picklist configuration. My customer wants it to be very simple (config via the UI is too difficult for them) so I'm making a .net program which allows them to load an excel spreadsheet, and then with 1 button overwrite the config in the org. For the sake of this question, I have created a sample bit of code which exhibits my errors.

Config: In salesforce campaign has 2 picklist fields, Master Channel and Reporting Channel. Reporting Channel's values are dependant on Master Channel.


public void Example()
  //Pull down current config of controlled picklist field
  CustomField reportCustomField = (CustomField)MetadataBinding.readMetadata("CustomField", new string[] { "Campaign.Reporting_Channel__c" })[0];

  //Create an example value for the controlled picklist
  ValueSettings setToAdd = new ValueSettings();

  setToAdd.valueName = "Example Controlled picklist value";
  setToAdd.controllingFieldValue = new List<string> { "Example Master picklist value" }.ToArray();
  //Wipe out all non-controlled values and set up all values which are related to a master value
  reportCustomField.valueSet.valueSetDefinition = null;
  reportCustomField.valueSet.valueSettings = new List<ValueSettings> { setToAdd }.ToArray();

  //Pull down current config of master field
  CustomField masterCustomField = (CustomField)MetadataBinding.readMetadata("CustomField", new string[] { "Campaign.Master_Channel__c" })[0];

  //Create an example value for the master picklist
  CustomValue setToAdd2 = new CustomValue();
  setToAdd2.fullName = "Example Master";

  //Set up the new values
  masterCustomField.valueSet.valueSetDefinition.value = new List<CustomValue> { setToAdd2}.ToArray();

  //Send the new configuration into Salesforce
  List<Metadata> toSend = new List<Metadata>() { masterCustomField, reportCustomField };
  MetaData.SaveResult[] metadataSR = MetadataBinding.updateMetadata(toSend.ToArray());
  //Iterate results, displaying errors/successes
  foreach (MetaData.SaveResult srInd in metadataSR)
    if (srInd.errors != null)
      foreach (MetaData.Error errInd in srInd.errors)
        System.Console.WriteLine(srInd.fullName.Replace("__c", "").Replace('_', ' ') + ": " + errInd.message, true);
      System.Console.WriteLine(srInd.fullName.Replace("__c", "").Replace('_', ' ') + " saved to Salesforce", false);

This code results in the following debug lines:

Campaign.Master Channel saved to Salesforce

Campaign.Reporting Channel: You must specify either picklist, globalPicklist, or valueSet.

I have a case open with Salesforce but as per usual I'm getting the run-around.

  • I'm wondering if the problem is related to the controllingFieldValue. If you look at the raw metadata in the example the controllingField is the API name of the parent picklist field. Where in your example you have "Example Master". Try keeping the __c and _ in place and working with the API names directly. – Daniel Ballinger Feb 14 '18 at 0:28
  • Ah sorry, the "Example Master" was actually an example value for the Master picklist, which then allows for "Example Controlled" to be chosen in the dependant picklist. – Ben Kiefer Feb 14 '18 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.