Мне нужно программно загрузить PDF-файлы в существующие записи Salesforce с помощью C# SOAP API.
Я видел этот вопрос, а также множество других, но все, что я нашел, либо не решило мою проблему, либо связано с другим языком или REST API. Вся информация о С# SOAP API, которую я могу найти, использует объект Вложение, который, похоже, не существует в API. Я использую Partner WSDL и правильно добавил его в качестве веб-ссылки в свой проект.
Объект EmailFileAttachment существует, но его нельзя преобразовать в sОбъект для сохранения в записи 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 имеет все правильные поля, которые мне нужны, но не может быть преобразован в sОбъект, поэтому я предполагаю, что это не тот объект, который нужно использовать, или что я собираюсь использовать его неправильно.
// 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
Обновлено: Согласно ответу superfell, я загрузил файл как sObject, который отлично работал. Единственным условием является то, что вложение должно быть созданный как новый объект Salesforce и связано с исходным объектом через поле идентификатор родителя. Вот рабочий код ниже
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);
Партнерский API включает только общее определение SObject, но не конкретные типы SObject. (поскольку ожидается, что партнеры захотят написать код один раз и динамически адаптировать его к схеме пользователей). Вам потребуется либо создать партнерский экземпляр SObject для вашего вложения, либо переключиться на корпоративный WSDL, который будет иметь конкретный класс вложения, который вы ищете. См. [1] для получения подробной информации о том, как объекты SObject выглядят в партнерском API. В C# есть пример партнерского API для создания экземпляра SObject в [2]. Вы должны иметь возможность изменить это, чтобы создать вложение вместо контакта.
[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
Использование 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);
}