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];
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.

  • I don't have such type ReadLayoutResult . – vortex Apr 20 '15 at 14:26
  • MetadataService.ReadLayoutResult – Peter de Jong Apr 20 '15 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 '15 at 14:33
  • At bit.ly/1yK5PGo , I read public class ReadLayoutResult implements IReadResult { <SNIP> } – Peter de Jong Apr 20 '15 at 14:35
  • Well, do i have to implement it manually in my generated MetadataService class? Is this going to help? – vortex Apr 20 '15 at 14:38
0

Are you missing the .getRecords() call?

Layout layout = (Layout)service.readMetadata("Layout", new string[] {"Object__c-Object Layout"}).getRecords()[0];
  • I don't have .getRecords() method. – vortex Apr 16 '15 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 '15 at 8:11
  • See my edited qustion. – vortex Apr 16 '15 at 8:24

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.