+ Start a Discussion
SuperfellSuperfell 

Create with foreign keys with partner API

Someone asked for an example of this, here's some code that creates a contact and uses an external ID on the account record to set the relationship to the account (rather than using the salesforce id for the account). The code assumes there's an field called extId__c on account which is flagged as an external Id, and that the account with the value ID_001 already exists.

 

 

            XmlDocument doc = new XmlDocument();
            XmlElement acc = doc.CreateElement("Account");
            XmlElement extId = doc.CreateElement("extId__c");
            extId.InnerText = "ID_001";
            XmlElement ty = doc.CreateElement("type");
            ty.InnerText = "Account";
            acc.AppendChild(ty);
            acc.AppendChild(extId);

            sf.sObject contact = new sf.sObject();
            contact.type = "Contact";
            XmlElement e1 = doc.CreateElement("FirstName");
            XmlElement e2 = doc.CreateElement("LastName");
            e1.InnerText = "Simon";
            e2.InnerText = "Fell";
            contact.Any = new XmlElement[] { e1, e2, acc };

            sf.SaveResult sr = s.create(new sf.sObject[] { contact })[0];
            if (sr.success)
                Console.WriteLine("new contact id is {0}", sr.id);
            else
                Console.WriteLine("Error {0} {1}", sr.errors[0].statusCode, sr.errors[0].message);

 

 

kmadminkmadmin

In case of custom objects (custom__c instead of "Account" in your example) should we be using __r instead of __c ?

SuperfellSuperfell

Yes, you use the name of the relationship.

kmadminkmadmin

I tried your sample in my app. I am trying to upsert account objects. Account object has a lookup relationship with branch custom object and instread of using branch custom object's ID, I would like to use branch custom object's external ID. So here is my code:

 

 

     if (ActiveDealerReader.IsDBNull((5)))
                    {
                        FieldsToNull.Add("Branch__c");
                    }
                    else
                    {
                        ActiveDealerElements[5] = Utility.CreateForeignKeyXmlElement("Branch__r", "Branch_Number__c",
                                                                               ActiveDealerReader.GetString(5));
                    }

 And here is the CreateForeignKeyXmlElement method:

 

 

public static XmlElement CreateForeignKeyXmlElement(string type, string extIdName, string extIdValue)
        {
            var Doc = new XmlDocument();
            var XmlEl = Doc.CreateElement(type);
            var ChildEl = Doc.CreateElement(extIdName);
            ChildEl.InnerText = extIdValue;
            var TypeEl = Doc.CreateElement("type");
            TypeEl.InnerText = type;
            XmlEl.AppendChild(TypeEl);
            XmlEl.AppendChild(ChildEl);

            return XmlEl;
        }

 

Now when I try to execute the upsert call. I get the following error:

 

The remote server returned an error: (500) Internal Server Error.

 

Here are the headers:

 

{User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.3603)
Content-Encoding: gzip
Accept-Encoding: gzip
VsDebuggerCausalityData: uIDPo34Gzm6tunJPs45lrgERyDIAAAAAE7b2+i93zESvJeyM4AlDDSNoDtkb2jNNsyXad7QiJ3MACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Host: na1-api.salesforce.com
Content-Length: 28069
Expect: 100-continue

}

 

BTW, I am using gzip compression on request and response and I am also using  a wrapper class to wrap the API calls and for batching.

SuperfellSuperfell

You'll need to look at the soap fault message returned with the 500 status code.

kmadminkmadmin

The message is "The remote server returned an error: (500) Internal Server Error." Is there something else in the exception that I should be looking for?

 

Another question, if I have a junction object can I use foreign keys of both the master objects to upsert data in the junction object?

SuperfellSuperfell

the response body should be a soap fault.

 

yes, you can use the FK resolution to resolve more than one foreign key on the row being operated on.

kmadminkmadmin

The reason I wasn't seeing what you were describing was because in .NET the soap faults are not returned in exception. I have inserted some code to parse the response stream and now see the soap fault:

 

The fault has to do with the Owner reference. I am inserting a contact and specifiying  account external ID and user external ID. The account external ID works fine but not the user external ID.Below is the code:

if (Reader.IsDBNull(9))
                    {
                        Elements[9] = Utility.CreateNewXmlElement("OwnerId",
                                                                        ConfigurationManager.AppSettings[
                                                                            "DefaultOwner"]);
                    }
                    else
                    {
                        [9] = Utility.CreateForeignKeyXmlElement("User","User_ID__c", Reader.GetString(9));
                    }

So I recieve the soap fault that there is no such field as "User" on Contact. So I try "Owner" and in that case I get there is no such field as "User_ID__c" on Owner.


What am I doing wrong?

 

SuperfellSuperfell

The containing element should be Owner, the child element called type should be User (the containing element is the name of the relationship, the child type element is the type of the thing its related to). You should look at the enterprise WSDL, even though you're not using it, the schema does describe the structure for this.

kmadminkmadmin

Got it working. Thanks for all your help.