1

Does anybody have an idea why i get the mentioned exception on the following line of code:

Layout layout =
   (Layout)service.readMetadata("Layout", new string[] {"Object__c-Object Layout"})[0];

I'm following the Andrew Fawcett blog here for read/update layout.

        public MetadataCreator(SalesforceContext context)
        {
            _metadataService = new MetadataService();
            _metadataService.Url = context.InstanceUrl + "/services/Soap/m/32.0/" + context.User.OrganizationId;
            _metadataService.SessionHeaderValue = new MetadataApiReference.SessionHeader();
            _metadataService.SessionHeaderValue.sessionId = context.AccessToken;           
        }
        private MetadataService _metadataService;

        public void GetLayout()
        {
            Layout result = (Layout)_metadataService.readMetadata("Layout", new string[] { "Macro-Macro Layout" })[0];
            //More code to follow
        }

EDIT: The ReadResult class was not generated.

<xsd:complexType name="ReadResult">
    <xsd:sequence>
     <xsd:element name="records" minOccurs="0" maxOccurs="unbounded" type="tns:Metadata"/>
     <xsd:element minOccurs="0" name="dummyFriend" type="tns:Metadata"/>
    </xsd:sequence>
</xsd:complexType>

After adding dummy element in the xml file, tha class was generated, but again I'm not able to cast Metadata to any other Metadata Type. From the Metadata API:

  1. Invoke the readMetadata() call. For the first argument, pass in the name of the metadata type. The metadata type must match one of the values returned by the describeMetadata() call. For the second argument, pass in an array of full names corresponding to the components you wish to get. The full names must match one or more full names returned by the listMetadata() call.

I have implementented the bellow Method

    public void GetLayout()
    {
        try
        {
            var describeMetadata = _metadataService.describeMetadata(32.0);
            var type = describeMetadata.metadataObjects.First(x => x.xmlName.Equals("Layout")).xmlName;

            var query = new ListMetadataQuery();
            query.type = type;
            var queries = new ListMetadataQuery[] { query };
            var fileProps = _metadataService.listMetadata(queries, 32.0);
            var layoutFullName = fileProps.FirstOrDefault(x => x.type.Equals(type)).fullName;

            var result = _metadataService.readMetadata(type, new string[] { layoutFullName });
            // ....
            }
            catch(Exception)
            {
                //....
            }
        }

The returned result contains a record with fullName=null and that behavior is for any Metadata Type.

The Solution Thanks to @Peter de Jong, i was able to fix this issue. I have translated the Java method to C# and adjust it to my needs the problem is gone.

public void readCustomObjectSync() { 
 try { 
     ReadResult readResult =
     metadataConnection.readMetadata("CustomObject", new String[] {"MyCustomObject1__c", "MyCustomObject2__c" }); 
     Metadata[] mdInfo = readResult.getRecords(); 
     System.out.println("Number of component info returned: " + mdInfo.length); 
     for (Metadata md : mdInfo) { 
        if (md != null) { 
            CustomObject obj = (CustomObject) md; 
            System.out.println("Custom object full name: " + obj.getFullName()); 
            System.out.println("Label: " + obj.getLabel()); 
            System.out.println("Number of custom fields: " + obj.getFields().length); 
            System.out.println("Sharing model: " + obj.getSharingModel()); 
        } else { 
            System.out.println("Empty metadata."); 
        } 
    } 
} catch (ConnectionException ce) { 
        ce.printStackTrace(); 
} 

}

The real cause of the problem:

I couldn't cast Metadata to type Layout, because the Full Name needs to be qualified twice with the Namespace. For example:

 MetadataService.Layout layout =
   (MetadataService.Layout) service.readMetadata('Layout',
      new String[] { 'PackagePrefix__Object__c-PackagePrefix__LayoutName' }).getRecords()[0];

2 Answers 2

1
+50

The readMetaData method results indeed in an instance of the implemented IReadResult Class. Can you cast the result of readMetaData to ReadLayoutResult and invoke .getRecords()? .getRecords should return a list of instantiated Metadata.

7
  • I don't have such type ReadLayoutResult .
    – vortex
    Apr 20, 2015 at 14:26
  • MetadataService.ReadLayoutResult Apr 20, 2015 at 14:29
  • No, just ReadResult. I have searched for it in the Metadata.xml, downloaded from salesforce, but it's not avialable there either.
    – vortex
    Apr 20, 2015 at 14:33
  • At bit.ly/1yK5PGo , I read public class ReadLayoutResult implements IReadResult { <SNIP> } Apr 20, 2015 at 14:35
  • Well, do i have to implement it manually in my generated MetadataService class? Is this going to help?
    – vortex
    Apr 20, 2015 at 14:38
0

Are you missing the .getRecords() call?

Layout layout = (Layout)service.readMetadata("Layout", new string[] {"Object__c-Object Layout"}).getRecords()[0];
3
  • I don't have .getRecords() method.
    – vortex
    Apr 16, 2015 at 8:04
  • readMetadata() should return an IReadResult, this interface has the getRecords() method so I'm not sure why you can't access it. Could you post more of your code for us to review?
    – Mark Keats
    Apr 16, 2015 at 8:11
  • See my edited qustion.
    – vortex
    Apr 16, 2015 at 8:24

You must log in to answer this question.

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