8

In the documentation it says

Apex code can create, read, and update (but not delete) custom metadata records

No where in the guide do I see apex being used to update custom metadata, only to create and read. I'd like to update the custom meta data in my org with apex. Are you only able to edit custom meta data if it's in another org and part of a managed packaged?

5 Answers 5

4

The Metadata.Operations class gives the ability to update/retrieve/insert metadata.

To answer your question about updating Custom Metadata, you'd be using the Metadata.Operations.enqueueDeployment();

I've provided the apex class you can create in your own org to reproduce.

1st steps: Create a Custom Metadata Type. If you'd like to use the code I provide verbatim, then follow these steps

  1. Create Custom Metadata Type, name it "Test Custom Metadata".
  2. Create a custom field named "Custom Field 1" of type Text.. api name would be Custom_Field_1__c
  3. Click on Manage Test Custom Metadata(create a custom metadata record), and enter in the values for label : "Before_Change", that will populate the name with Before_Change as well. Enter in any text for the Custom_Field_1__c, for me, I put 'Testing before changes'.(This will be updated once the code is run)
  4. Your custom metadata is all set up, and now it's time to create the apex class
  5. Create an Apex Class named MetadataDeploy
  6. Populate the following apex class with the code below.
public without sharing class MetadataDeploy implements Metadata.DeployCallback{

    public List<FieldWrapper> listField{get;set;}
    public class FieldWrapper
    {
        public String fieldName {get; set;}
        public String fieldAPIName {get; set;}
    }
   
    public static String updateCustomMetadata()
    {
        try {
        Test_Custom_Metadata__mdt tcm = getMetaDataRecords()[0]; //retrieving custom metadata records, using the first.
        Id customMetadataId = tcm.Id;
        system.debug('CustomMetadata Id ' + customMetadataId);
        Metadata.CustomMetadata customMetadata = new Metadata.CustomMetadata();
        customMetadata.fullName = 'Test_Custom_Metadata.Before_Change'; //custom metadata name
        customMetadata.label = 'Before_Change';
        // customMetadata.id = customMetadataId;
        Metadata.CustomMetadataValue customField1 = new Metadata.CustomMetadataValue(); //the values you're changing/updating
        customField1.field = 'Custom_Field_1__c'; //the custom field API Name that you're wanting to insert/update a value of
        customField1.value = 'FIeld Test 1 after';
        customMetadata.values.add(customField1);//add the changes to list of changes to be deployed
       
        // if(customMetadataId != null) //if a custom metadata record exists, add the id here
        // {
        //     Metadata.CustomMetadataValue customId = new Metadata.CustomMetadataValue();
        //     customId.field = 'Id';
        //     customId.value = customMetadataId;
        //     customMetadata.values.add(customId);
        // }
        
        Metadata.DeployContainer mdContainer = new Metadata.DeployContainer();
        mdContainer.addMetadata(customMetadata);
        
        MetadataDeploy callback = new MetadataDeploy();
        // Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, null);
        
        Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, callback);
        
        system.debug('jobId is ' + jobId);
        
        // Metadata.DeployContainer metaDeploy1 = new Metadata.DeployContainer();
        // metaDeploy1.addMetadata(approvalConfigToInsert);
        // Id AsynchResult1 = Metadata.Operations.enqueueDeployment(metadeploy1, null);
        // system.debug('jobId ' + mdContainer);
        return 'Success';
            
        } catch (Exception e) {
                return e.getMessage();
        }
        }
        public static list<Test_Custom_Metadata__mdt> getMetaDataRecords()
        {
            list<Test_Custom_Metadata__mdt> tcm = [Select Id, label FROM Test_Custom_Metadata__mdt];
            return tcm;
        }
       
    
        // find all sObjects available in the organization
        public void handleResult(Metadata.DeployResult result, Metadata.DeployCallbackContext context) {
            if(result.status == Metadata.DeployStatus.SUCCEEDED)
            {
                //success
                System.debug(' ===>'+ result);
            }else{
                //not success
                System.debug(' ===> fail '+ result);
            }
            
        }
}

Open up your developer console, and execute MetadataDeploy.updateCustomMetadata();

You can check the results in deployment status, or the logs where it says QueueableHandler.

Check the Custom Metadata Record and see if it updated to 'FIeld Test 1 after', if it did, it successfully deployed the change.

TLDR: You can update Custom Metadata by using the Metadata.Operations.enqueueDeployment(metadataContainer, callback). The metadataContainer is basically setting up the package to deploy, which would be Metadata.CustomMetadata, filling out the values that you want to change (Metadata.CustomMetadataValue), and placing it in the metadata container(Metadata.DeployContainer.add(customMetadata). The callback is a way for the results to be handled, so if it failed or succeeded, you can get a response back.

2
  • Will you please suggest this by creating a method that will accept the API name or required values as a parameters to update the metadata ..this will bring more usability of this code ..anyway nice try.
    – vaibhav
    Commented Apr 25, 2023 at 12:52
  • 1
    Above code will not work for an update of a record. In particular this line customId.field = 'Id'; throws an error saying "Invalid field: Id". In order to update one needs to use Metadata.Operations.retrieve() method provided by Salesfroce.
    – Arthlete
    Commented Dec 1, 2023 at 20:10
5

I have created one small utility which we can use to create, update custom metadata record. Here we just need to pass CMDT list and it will handle the insert/update.

//Update records
List<Test_metadata__mdt> MetadataList1 = [SELECT MasterLabel, DeveloperName,Name__c, Account_Number__c FROM Test_metadata__mdt]; //MasterLabel, DeveloperName is required when query as we need them in update
MetadataList1[0].Account_Number__c = 986532;
MetadataList1[0].Account_Number__c = 659823;
String jobId2 = MetaDataUtility.upsertMetadata(MetadataList1);

You can check that here.

1
4

This can be accomplished with Apex Metadata API. Please check out this trailhead module:

https://trailhead.salesforce.com/en/content/learn/modules/apex_metadata_api

1
  • 1
    Link is not working, it is recommended to provide an excerpt from an article when posting a link.
    – Arthlete
    Commented Dec 1, 2023 at 19:17
3

The accepted answer will not work for updating custom metadata. You can't assign id field using the CustomMetadataValue class, it throws an error saying Unsupported type 'Id' for field name 'value'.

Instead one should use the Operations Metadata class to first retrieve the custom metadata in question like so:

List<Metadata.Metadata> components = Metadata.Operations.retrieve(Metadata.MetadataType.CustomMetadata, new List<String> { 'My_Custom_Metadata__mdt.myDeveloperName' });

Then assign that to a custom CustomMetadata class instance:

Metadata.CustomMetadata customMetadataRecord = (Metadata.CustomMetadata) components.get(0);

Then modify any fields in question:

Metadata.CustomMetadataValue myCustomField = new Metadata.CustomMetadataValue();
myCustomField.field = 'My_Custom_Field__c';
myCustomField.value = 'RandomValue';
customMetadataRecord.values.add(myCustomField);

Then add this record to a DeployContainer:

Metadata.DeployContainer myContainer = new Metadata.DeployContainer();
myContainer.addMetadata(customMetadataRecord);

And finally enqueue that for deployment:

MyCallbackClass callback = new MyCallbackClass();
Metadata.Operations.enqueueDeployment(myContainer, callback);
2

There's a nifty gitHub library from Andrew Fawcett that makes doing this somewhat easier. Motivation and detail on his blog

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .