Загрузка вложения в Salesforce с помощью C# SOAP API

Мне нужно программно загрузить 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);
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 537
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Партнерский 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);
        }

Другие вопросы по теме