使用C#SOAP API将附件上传到Salesforce

时间:2019-04-08 22:06:07

标签: c# api soap salesforce

我需要使用C#SOAP API以编程方式将PDF文件上传到现有Salesforce记录。

我见过this question以及无数其他人,但是我发现的所有内容都没有解决我的问题,或者与另一种语言或REST API有关。我能够找到的所有C#SOAP API信息都使用附件对象,该对象似乎在API中不存在。我正在使用合作伙伴WSDL,并将其作为Web参考正确添加到我的项目中。

确实存在一个 EmailFileAttachment 对象,但是无法将其强制转换为 sObject 以保存到Salesforce记录中。

这是我当前拥有的代码,我可以更新数据字段。

// Login
var Binding = new SforceService();
var loginResult = Binding.login("Username", "Password");
Binding.Url = loginResult.serverUrl;
Binding.SessionHeaderValue = new SessionHeader();
Binding.SessionHeaderValue.sessionId = loginResult.sessionId;

// Create sObject, update data
var obj = new sObject();
obj.type = "tableName";
obj.Id = "objId";

var document = new XmlDocument();
var nodeList = new List<XmlElement>();

var dataNode = document.CreateElement("fieldName");
dataNode.InnerText = "fieldValue";
nodeList.Add(dataNode);

obj.Any = nodeList.ToArray();

// Save data
sObject[] objArray = { obj };
var saveResults = Binding.update(objArray);

但是我无法使用附件 EmailFileAttachment 。我所知道的Salesforce API名称空间中没有附件 EmailFileAttachment 具有我需要的所有正确字段,但是无法转换为 sObject ,所以我猜测它不是要使用的正确对象,或者我正在使用不正确。

// The type or namespace 'Attachment' could not be found.
//var attachment = new Attachment;

var attachment = new EmailFileAttachment();
attachment.id = "objId";
attachment.fileName = "filename.pdf";
attachment.body = fileData; // fileData is byte[]

// Cannot implicitely convert EmailFileAttachment to sObject.
var objArray = new sObject[] { attachment };

我是否缺少一些可以使用附件的东西,或者还有另一种方法可以做到这一点?

编辑:我正在使用Salesforce C#SOAP API v45.0


编辑:按照超跌的回答,我将文件作为sObject上传,效果很好。 唯一的规定是必须作为新的Salesforce对象创建附件,并通过 ParentId 字段将其链接到原始对象。 这是下面的工作代码

var atObj = new sObject();

// Set type as "Attachment"
atObj.type = "Attachment";

var document = new XmlDocument();
var nodeList = new List<XmlElement>();

// Set Filename
var nameNode = document.CreateElement("Name");
nameNode.InnerText = "testfile.pdf";
nodeList.Add(nameNode);

// Set ParentId - this is the object id you want to link the attachment to
var idNode = document.CreateElement("ParentId");
idNode.InnerText = "objId";
nodeList.Add(idNode);

// Set File Data - use Base64 string conversion
string encoded = Convert.ToBase64String(fileData); // fileData is byte[]
var dataNode = document.CreateElement("Body");
dataNode.InnerText = encoded;
nodeList.Add(dataNode);

atObj.Any = nodeList.ToArray();
sObject[] objArray = { atObj };

// Use create(), not update()
var saveResults = Binding.create(objArray);

2 个答案:

答案 0 :(得分:1)

合作伙伴API仅包含通用SObject定义,没有具体的SObject类型。 (因为它期望合作伙伴希望只编写一次代码并使它动态适应用户模式)。您将需要为您的附件构建伙伴SObject实例,或者切换到将具有您要查找的具体Attachment类的企业WSDL。有关SObjects在伙伴API中的外观的详细信息,请参见[1]。在C#中有一个示例,用于合作伙伴API在[2]处创建一个SObject实例。您应该可以更改它以创建附件而不是联系人。

[1] https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_partner_objects.htm

[2] https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sample_create_call.htm#topic-title

答案 1 :(得分:0)

使用 Enterprise WSDL / SOAP 将文件 / ContentDocument 附加到我需要创建 ContentVersion 的对象,然后 Salesforce 创建 ContentDocument,然后创建 ContentDocumentLink 以将其附加到对象。

 Byte[] bytes = File.ReadAllBytes(filePath);
            
 ContentVersion cv = new ContentVersion();
 cv.Title = Path.GetFileName(filePath);
 cv.PathOnClient = filePath;
 cv.VersionData = bytes;
 cv.Origin = "H";

SaveResult[] createResults = _sfClient.create(new sObject[] { cv });

 if (createResults.Count() > 0 && createResults[0].success)
                {
                    cv.Id = createResults[0].id;

                    QueryResult queryResult = _sfClient.query(string.Format("select Id, ContentDocumentId from ContentVersion where Id = '{0}'", cv.Id));

                    if (queryResult.records == null) return null;

                    sObject[] records = queryResult.records;

                    //we can loop through the returned records
                    if (records.Length > 0)
                    {
                        List<ContentVersion> cvs = new List<ContentVersion>(queryResult.records.Cast<ContentVersion>());
                        ContentDocumentLink contentLink = new ContentDocumentLink();
                        contentLink.LinkedEntityId = sfCase.Id;
                        contentLink.ContentDocumentId = cvs.First().ContentDocumentId;
                        contentLink.ShareType = "V"; 
                        contentLink.IsDeleted = false;
                

                        SaveResult[] createResults1 = _sfClient.create(new sObject[] { contentLink });

                        if (createResults1.Count() > 0 && createResults1[0].success)
                        {

                            return createResults1[0].id;
                        }
                        else if (createResults1.Count() > 0)
                        {
                            return "Error. Case Content Document Failed. Case Number: [" + Helpers.Trim(sfCase.Case_Number__c) + "] had an error inserting. The error reported was: " + createResults1[0].errors[0].message;
                        }
                    }

                }
                else if (createResults.Count() > 0)
                {
                    return "Error. Case Content Version Failed. Case Number: [" + Helpers.Trim(sfCase.Case_Number__c) + "] had an error inserting. The error reported was: " + createResults[0].errors[0].message;
                }
            }
            catch (Exception ex)
            {
                return string.Format("Upsert {0}", ex.Message);
        }