2

We're trying to pull down picklist values from the Contact object to show on an ASP.Net page using the Partner API. However, we receive the following error when the describeSObject call is made.

"Instance validation error: 'urn:address' is not a valid value for soapType."

It appears that the API can not handle objects with compound fields such as address.

Here is a snippet of the code which we are using.

public sforce.DescribeSObjectResult[] getTableOfPickListValues(string fieldName, string[] objectName)
{
    List<string> aList = new List<string>();

    try
    {
        binding.QueryOptionsValue = new sforce.QueryOptions();
        binding.QueryOptionsValue.batchSize = 500;
        binding.QueryOptionsValue.batchSizeSpecified = true;
        return binding.describeSObjects(objectName);
    }
    catch (Exception error)
    {

    }
}

We've tried old and new versions of the API/WSDL and this issue appears to persist throughout.

Is this a known issue with the Salesforce partner API or are we doing something wrong? I can't seem to find anyone having reported this before...

For what it's worth, we've done this several times for custom objects so we know our code works.

  • @TusharSharma Thanks for the help but the issue lies in the binding.describeSObjects(objectName); call which we can't change. We're not specifically querying for an address field but the describeSObjects bring back all field definitions. – William Smith Jul 12 '18 at 9:49
  • Can you add filter in your code to skip this field. – Tushar Sharma Jul 12 '18 at 9:53
  • 1
    @TusharSharma The error occurs before anything is returned so filtering anything is impossible. – William Smith Jul 12 '18 at 10:11
  • 1
    I have definitely been able to load picklists from the SOAP API/Partner WSDL using describeSObject/describeSObjects, although I can't seem to remember which method. I'll see if I can find some example code. – dana Jul 12 '18 at 12:37
1

So you are doing a describeSObjects for Contact and there is a problem with urn:address coming back in the response.

Firstly, while you might be changing the WSDL for each API version, make sure that the endpoint API version matches. The namespace for the soapType enumerations location and address were changed between v34.0 and v35.0 (See also - Salesforce winter 16 breaking the partner wsdl changes related to tns and uns namespace conflict). An API version mismatch could certainly produce unexpected results.

Next up I'd look at the raw SOAP response coming back from the Partner API. I use SOUP UI to test this sort of directly request.

Request:

URL: https://mydomain-dev-ed.my.salesforce.com/services/Soap/u/43.0/00D7F0000000001

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
   <soapenv:Header>
      <urn:SessionHeader>
         <urn:sessionId>00D7F0000000001!AR_not_a_real_session_id_ySaEz_JEf1jRuJcPl7KJAT0</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:describeSObjects>
         <urn:sObjectType>Contact</urn:sObjectType>
      </urn:describeSObjects>
   </soapenv:Body>
</soapenv:Envelope>

Response:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Header>
      <LimitInfoHeader>
         <limitInfo>
            <current>8</current>
            <limit>15000</limit>
            <type>API REQUESTS</type>
         </limitInfo>
      </LimitInfoHeader>
   </soapenv:Header>
   <soapenv:Body>
      <describeSObjectsResponse>
         <result>
            <activateable>false</activateable>
            <!-- ... --> 
            <fields>
               <!-- ... --> 
               <label>Other Address</label>
                <!-- ... --> 
               <name>OtherAddress</name>
               <!-- ... --> 
               <soapType>tns:address</soapType>
               <!-- ... --> 
            </fields>
            <!-- ... --> 
            <fields>
               <!-- ... --> 
               <label>Mailing Address</label>
               <!-- ... --> 
               <name>MailingAddress</name>
               <!-- ... --> 
               <soapType>tns:address</soapType>
               <!-- ... --> 
            </fields>
            <!-- ... --> 
            <keyPrefix>003</keyPrefix>
            <label>Contact</label>
            <labelPlural>Contacts</labelPlural>
            <!-- ... --> 
         </result>
      </describeSObjectsResponse>
   </soapenv:Body>
</soapenv:Envelope>

So that seems fine for a v43.0 Partner API call where I'd expect the namespace to be tns (urn:partner.soap.sforce.com).

Check your generated C# proxy code. I have the following:

 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.2612.0")]
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:partner.soap.sforce.com")]
    public enum fieldType {
        @string,            
        // ...            
        location,           
        address,
        anyType,
        complexvalue,
    }

and

 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.2612.0")]
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:partner.soap.sforce.com")]
    public enum soapType {
        [System.Xml.Serialization.XmlEnumAttribute("tns:ID")]
        tnsID,
        [System.Xml.Serialization.XmlEnumAttribute("xsd:base64Binary")]
        xsdbase64Binary,
        //...
        [System.Xml.Serialization.XmlEnumAttribute("tns:location")]
        tnslocation,
        [System.Xml.Serialization.XmlEnumAttribute("tns:address")]
        tnsaddress,
        [System.Xml.Serialization.XmlEnumAttribute("xsd:anyType")]
        xsdanyType,
        //...
    }

Note how address has the expected tns namespace.

  • Thank you for your detailed response. I can't believe my stupidity but as you suggested we were updating the WSDL but using an old API number. We specifically set the URL, so we can easily switch between sandbox and live, instead of using the default. I'm surprised none of us spotted it over here - we were obviously on the ball yesterday! Thank you again for your help. – William Smith Jul 13 '18 at 8:35
1

Create a new console app with the following code:

using System;
using System.Configuration;

namespace SforcePartner
{
    class Program
    {
        static void Main(string[] args)
        {
            SforceService sforce = new SforceService();
            sforce.Url = ConfigurationManager.AppSettings["LoginUrl"];
            LoginResult loginResult = sforce.login(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"]);

            sforce.Url = loginResult.serverUrl;
            sforce.SessionHeaderValue = new SessionHeader { sessionId = loginResult.sessionId };
            DescribeSObjectResult[] describeSObjectResults = sforce.describeSObjects(new[] { "Account" });

            Console.WriteLine("{0} has {1} fields",
                    describeSObjectResults[0].name,
                    describeSObjectResults[0].fields.Length
                );
            Console.ReadLine();
        }
    }
}

Copy SforceService.wsdl to your project folder. Open the VS Command Prompt as follow:

Start -> Visual Studio 2017 -> Developer Command Prompt for VS 2017

Run cd to change to the project folder and build the Soap proxy as follows:

wsdl SforceService.wsdl /namespace:SforcePartner

Open the generated SforceService.cs in a text editor. Find ListViewRecordColumn[][] and replace it with ListViewRecordColumn[]. Now add SforceService.cs to your project.

  • 1
    Thank you for your response Dana, I really appreciate the help. It turns out we were updating the WSDL but not the API number. I can't believe it, we had three developers looking at it at one point! It's good to know about parsing the WSDL through WSDL.exe, it's not something I've used before but could see myself doing so in the future. – William Smith Jul 13 '18 at 8:36
  • Glad you figured it out :) I think we may have something in place that extracts the version number from the generated proxy for this very reason. We can switch between the test.salesforce.com and login.salesforce.com domain using the extracted version number. – dana Jul 13 '18 at 12:06

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.