I am trying to integrate with SOAP web services from SalesForce. My goal is to simply pull down the user data from SalesForce so we can integrate it into our system. I am able to login successfully using the proxy class (C#) I generated from the partner WSDL on the SalesForce website. The next thing I want to do is query the Users, pulling down FirstName, LastName, ect...
It is important to know that I was forced to modify the generated proxy code because it generated incorrectly. It populated the xml serialization fields to match private fields which throws an exception when making web service calls. It also generated a blank namespace for the "Any" property of the sObject class which I removed. I took advice from this StackOverflow topic if you'd like to see why I made these choices.
This is what my query looks like:
The qResult contains exactly 3 records (which is accurate since I only have 3 users). The issue is that every property on the sObject except "type" are always null.
I can't figure if I am making a simple error when trying to query or if the fact that I had to modify the proxy class and remove the namespace on the Any field is causing this issue. I am not sure what to do at this point. That same query in the developer console (at SalesForce.com) returns the correct data. It's also worth mentioning that my result of the query returned the proper amount of elements, they just don't have any data in them. It must be something simple... like adding back the namespace binding but figuring out what it should be or adding an xmlbinding to the property.
I was just wondering if anyone knew what to do about this. Maybe someone has had the same thing happen to them?
EDIT: So I took the time to perform some incredibly hacky techniques for intercepting requests from the generated webservice client, and I ended up getting the raw data that is being sent from SalesForce in response to my request. Here it is:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
<soapenv:Body>
<queryResponse>
<result xsi:type="QueryResult">
<done>true</done>
<queryLocator xsi:nil="true"/>
<records xsi:type="sf:sObject">
<sf:type>User</sf:type>
<sf:Id xsi:nil="true"/>
<sf:FirstName>Bob</sf:FirstName>
<sf:LastName>Dyllan</sf:LastName>
<sf:Email>bob@bob.com</sf:Email>
<sf:CompanyName xsi:nil="true"/>
<sf:Phone xsi:nil="true"/>
<sf:Title xsi:nil="true"/>
</records>
<records xsi:type="sf:sObject">
<sf:type>User</sf:type>
<sf:Id xsi:nil="true"/>
<sf:FirstName>Zachary</sf:FirstName>
<sf:LastName>Sheppard</sf:LastName>
<sf:Email>some_guy@yahoo.com</sf:Email>
<sf:CompanyName>Yahoo</sf:CompanyName>
<sf:Phone xsi:nil="true"/>
<sf:Title xsi:nil="true"/>
</records>
<records xsi:type="sf:sObject">
<sf:type>User</sf:type>
<sf:Id xsi:nil="true"/>
<sf:FirstName xsi:nil="true"/>
<sf:LastName>Chatter Expert</sf:LastName>
<sf:Email>noreply@chatter.salesforce.com</sf:Email>
<sf:CompanyName xsi:nil="true"/>
<sf:Phone xsi:nil="true"/>
<sf:Title xsi:nil="true"/>
</records>
<size>3</size>
</result>
</queryResponse>
</soapenv:Body>
</soapenv:Envelope>
It does seem to a serialization issue with the "sf" properties on these sObjects... but how do I make that match up with my C#? Here is the C# as it currently is for the sObject class:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:sobject.partner.soap.sforce.com")]
public partial class sObject
{
/// <remarks/>
public string type;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("fieldsToNull", IsNullable=true)]
public string[]
fieldsToNull;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public string
Id;
/// <remarks/>
public System.Xml.XmlElement[]
Any;
}
After an incredibly long day of research and frustration, I finally came across the correct attribute for this "Any" property of SalesForce's sObject class. SalesForce was trying to scrape up the relevant xml elements into this sObject class which allows them to leave the sObject class as a dynamic type. So in order to force the C# class to scrape in all the xml tags into the "Any" property we simply apply this:
So to be clear, When you generate the WSDL from your SalesForce account it may not be correct out of the box. You will need to rename some string arguments that are passed into attributes as well as replace the empty namespace on the "Any" property of the sObject class with the XmlAnyElement attribute in order to get a successful result from the query call of the API. The changes needed to make the client function can be found in this StackOverflow topic topic.
I am now able to successfully call the query function of the SalesForce API and get back the fields I queried for... I feel so much better!