[SalesForce] Creating Soap API request from apex

I have used Partner WSDL and created an apex class. I am trying to connect to force.com to get the records. I just started this as an example to get familiar with the SOAP API.

I actually want to use the SOAP API to create and delete the UserTerritory records. I need SOAP API for this because DML on UserTerritory are not supported in apex.

As a start I have created the snippet to get some records using the API, but I am getting an error

Web service callout failed: Unable to parse callout response. Apex type not found for element Name

Code Snippet:

partnerSoapSforceCom.Soap partner = new partnerSoapSforceCom.Soap();
partner.endpoint_x = 'https://login.salesforce.com/services/Soap/u/39.0';

partnerSoapSforceCom.LoginResult lr = partner.login('UserName', 'Password' + 'SecurityToken');
partnerSoapSforceCom.SessionHeader_element header = new 
partnerSoapSforceCom.SessionHeader_element();
header.sessionId = UserInfo.getSessionId();
partner.SessionHeader=header;
partnerSoapSforceCom.QueryResult qr = partner.query('Select Id, Name from Account limit 1');

Best Answer

The short answer is that the Partner API WSDL contains features that the native version of wsdl2apex doesn't support.

In particular, the problem here with you example code is the any element on the dynamic sObject complexType.

<complexType name="sObject">
    <sequence>
        <element name="type"               type="xsd:string"/>
        <element name="fieldsToNull"       type="xsd:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
        <element name="Id"                 type="tns:ID" nillable="true" />
        <any namespace="##targetNamespace" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
    </sequence>
</complexType>

Basically, an sObject can have any number of additional fields defined in the result. WebServiceCallout.invoke doesn't know how to handle that. See Supported WSDL Features.


As a proof on concept for the API call test, just try omitting the Name from the SOQL query. E.g.

partnerSoapSforceCom.Soap partner = new partnerSoapSforceCom.Soap();
partner.endpoint_x = URL.getSalesforceBaseUrl().toExternalForm() + '/services/Soap/u/39.0';

partnerSoapSforceCom.SessionHeader_element header = new partnerSoapSforceCom.SessionHeader_element();
header.sessionId = UserInfo.getSessionId();
partner.SessionHeader=header;
partnerSoapSforceCom.QueryResult qr = partner.query('Select Id from Account limit 1');