The Metadata Calls describeMetadata and listMetadata

The last couple of weeks I have been exploring the Deploy and Retrieve calls of the Metadata API for Salesforce. These calls have worked great for their purpose of sending and receiving the metadata files within a zip file. But what if you do not want to work with the actual files and you just want to see a listing of the current files? Also, what if you do not want to hard-code the types of metadata files in Salesforce, but you would rather work generically against all file types? It is for these situations where the describeMetatdata and listMetadata API calls come into play.

The describeMetadata call takes only the API Version as a parameter. The API Version parameter is important as new metatdata file types can become available with each new Salesforce release.

Version 10 of the Metadata API had only these types:
Scontrol, ApexPage, CustomObject, Document, CustomTab, CustomApplication, ApexClass, ApexTrigger, Profile

Version 26 of the Metadata API has these types:
CustomLabels, StaticResource, Scontrol, ApexComponent, ApexPage, Queue, CustomObject, ReportType, Report, Dashboard, Layout, Document, CustomPageWebLink, CustomTab, CustomApplicationComponent, CustomApplication, Portal, Letterhead, EmailTemplate, Workflow, Role, Group, HomePageComponent, HomePageLayout, CustomObjectTranslation, Translations, Flow, ApexClass, ApexTrigger, Profile, PermissionSet, DataCategoryGroup, AnalyticSnapshot, EntitlementTemplate, RemoteSiteSetting, CustomSite, LeadSharingRules, CampaignSharingRules, CaseSharingRules, ContactSharingRules, OpportunitySharingRules, AccountSharingRules, CustomObjectSharingRules, SecuritySettings, MobileSettings

Salesforce has come a long ways since version 10!

The code below is calling the describeMetadata and listMetadata Metadata API calls in VB.NET.  Before this code can be called you must use the Partner API to log into Salesforce to get the necessary token for subsequent calls.  Please see my previous blogs for this login code.

The nice part about this code is that it is generic and will work with future versions of the Metadata API.  As new Metadata types are returned from the describeMetatdata call, then those new types can be explored using the listMetadata call.

I hope this code gives you some ideas on how you can use the Metadata API call in your own projects and utilities.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
Private Sub DoListing()
        Dim dlistQueries(0 To 0) As SFMetadataAPI.ListMetadataQuery
        Dim listQuery As New SFMetadataAPI.ListMetadataQuery
        Dim myFPs() As SFMetadataAPI.FileProperties
        Dim dmeta As SFMetadataAPI.DescribeMetadataResult
        Dim sTemp As String
        'This call will get all the Metadata types under the Api Version 26.
        'By using this call first we do not need to hard-code the type property on the ListMetatdataQuery object
        'This way when new Metadata types are added to the API they would automatically be available
        'http://www.salesforce.com/us/developer/docs/api_meta/index_Left.htm#CSHID=meta_listmetadata.htm|StartTopic=Content%2Fmeta_listmetadata.htm|SkinName=webhelp
        dmeta = sfMetaData.describeMetadata(26)
        For Each item As SFMetadataAPI.DescribeMetadataObject In dmeta.metadataObjects
            If item.inFolder Then
                'Report, Dashboard, Document, EmailTemplate
                'I have not figured our perfectly how to set the folder property yet
                'listQuery.folder = ""
            Else
                'All others are false
                'listQuery.folder = ""
            End If
            sTemp = item.directoryName 'The name of the directory in the .zip file that contains this component.
            sTemp = item.suffix 'This is the suffix of the file labels=CustomLabels, resource=StaticResource, scf=Scontrol,
            ' component=ApexComponent, page=ApexPage, queue=Queue, object=CustomObject, reportType=ReportType,
            ' report=Report, dashboard=Dashboard, layout=Layout, weblink=CustomPageWebLink, tab=CustomTab,
            ' customApplicationComponent=CustomApplicationComponent, app=CustomApplication, portal=Portal,
            ' letter=Letterhead, email=EmailTemplate, workflow=Workflow, role=Role, group=Group, homePageComponent=HomePageComponent,
            ' homePageLayout=HomePageLayout, objectTranslation=CustomObjectTranslation, translation=Translations, flow=Flow,
            ' cls=Apexclass, trigger=ApexTrigger, profile=Profile,
            ' permissionset=PermissionSet, datacategorygroup=DataCategoryGroup, snapshot=AnalyticSnapshot, entitlementTemplate=EntitlementTemplate,
            ' remoteSite=RemoteSiteSetting, site=CustomSite, sharingRule=LeadSharingRules, sharingRules=CampaignSharingRules,
            ' sharingRules=CaseSharingRules, sharingRules=ContactSharingRules, sharingRules=OpportunitySharingRules,
            ' sharingRules=AccountSharingRules, sharingRules=CustomObjectSharingRules, settings=SecuritySettings,
            ' settings=MobileSettings
            'Nothing for Document,
            sTemp = item.metaFile 'If a file is involved.
            'False for CustomLabels, Queue, CustomObject, ReportType, Report, Dashboard, Layout, CustomPageWebLink,
            ' CustomTab, CustomApplicationComponent, CustomApplication, Portal, Letterhead, Workflow, Role,
            ' Group, HomePageComponent, HomePageLayout, CustomObjectTranslation, Translations, Flow, Profile,
            ' PermissionSet, DataCategoryGroup, AnalyticSnapshot, EntitlementTemplate, RemoteSiteSetting, LeadSharingRules
            ' CaseSharingRules, ContactSharingRules, OpportunitySharingRules, AccountSharingRules, CustomObjectSharingRules,
            ' SecuritySettings, MobileSettings
            'True for StaticResource, Scontrol, ApexComponent, ApexPage, EmailTemplate, ApexClass, ApexTrigger, CustomSite, Document
            'sTemp = item.metaFileField - This is private
            'There is a childXmlNames array.  It is populated for StaticResource, CustomLabels, CustomObject, LeadSharingRules,
            ' CampaignSharingRules, CaseSharingRules, ContactSharingRules,
            ' OpportunitySharingRules, AccountSharingRules, CustomObjectSharingRules
            'Version 26 of the API has these types
            'CustomLabels, StaticResource, Scontrol, ApexComponent, ApexPage, Queue, CustomObject, ReportType, Report, Dashboard, Layout,
            ' Document, CustomPageWebLink, CustomTab, CustomApplicationComponent, CustomApplication, Portal, Letterhead, EmailTemplate,
            ' Workflow, Role, Group, HomePageComponent, HomePageLayout, CustomObjectTranslation, Translations, Flow, ApexClass, ApexTrigger,
            ' Profile, PermissionSet, DataCategoryGroup, AnalyticSnapshot, EntitlementTemplate, RemoteSiteSetting, CustomSite, LeadSharingRules,
            ' CampaignSharingRules, CaseSharingRules, ContactSharingRules, OpportunitySharingRules, AccountSharingRules, CustomObjectSharingRules,
            ' SecuritySettings, MobileSettings
            listQuery.type = item.xmlName 'CustomField / CustomObject / ApexClass / ApexPage / ApexTrigger
            'Version 10 of the API only has these types
            ' Scontrol, ApexPage, CustomObject, Document, CustomTab, CustomApplication, ApexClass, ApexTrigger, Profile
            dlistQueries(0) = listQuery
            'The dlistQueries can have up to three ListMetatdataQuery items in it
            'In this example we are just getting them one at a time.
            myFPs = sfMetaData.listMetadata(dlistQueries, 26)
            If myFPs Is Nothing Then
                'There was nothing returned from the listMetadata call
            Else
                'The array of FileProperties gives us the details about each of the metadata files
                For Each fileProps As SFMetadataAPI.FileProperties In myFPs
                    sTemp = fileProps.id
                    sTemp = fileProps.fileName 'This will contain the folder too: ApexClasses/myfile.cls
                    sTemp = fileProps.fullName 'This just contains the file name without the extension: myfile
                    sTemp = fileProps.createdById
                    sTemp = fileProps.createdByName
                    sTemp = fileProps.createdDate
                    sTemp = fileProps.manageableState 'unmanaged
                    sTemp = fileProps.manageableStateSpecified
                    sTemp = fileProps.namespacePrefix
                    sTemp = fileProps.lastModifiedById
                    sTemp = fileProps.lastModifiedByName
                    sTemp = fileProps.lastModifiedDate
                    sTemp = fileProps.type 'CustomField / CustomObject / ApexClass / ApexPage
                Next
            End If
        Next
        'Besides the metadataObjects property there are three others on the
        ' describeMetadataResult object
        'The namespace of the organization. Specify only for Developer Edition organizations that can contain a managed package.
        ' The managed package has a namespace specified when it is created.
        sTemp = dmeta.organizationNamespace
        'Indicates whether rollbackOnError is allowed (true) or not (false).
        ' This(value Is always)
        '  false in production organizations.
        '  the opposite of testRequired.
        sTemp = dmeta.partialSaveAllowed
        'Indicates whether tests are required (true) or not (false).
        ' This is only true in a production org.  It is false in sandboxes and developer orgs
        sTemp = dmeta.testRequired
End Sub
This entry was posted in Technology and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>