function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Chad JoubertChad Joubert 

Need a little help adding an attachment to an object

I have been able to update fields and add documents to SalesForce but I am having trouble adding an attachment to an object such as an opportunity.  If anyone can see what I am missing that would be a great help.  
 
protected async Task LoadDocument(string parentObjectID)
        {
          
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;

            var auth = new AuthenticationClient();
            var url = IsSandboxUser.Equals("true", StringComparison.CurrentCultureIgnoreCase)
                ? "https://test.salesforce.com/services/oauth2/token"
                : "https://login.salesforce.com/services/oauth2/token";

            await auth.UsernamePasswordAsync(ConsumerKey, ConsumerSecret, Username, Password, url);

            string boundary = "----" + DateTime.Now.Ticks.ToString("x");

            var uri = auth.InstanceUrl + "/services/data/v37.0/sobjects/attachment/";
            //var uri = auth.InstanceUrl + "/services/data/v37.0/sobjects/Document/";

            var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
            req.Headers.Add("Authorization: OAuth " + auth.AccessToken);
            req.ContentType = "multipart/form-data; boundary=" + boundary;
            req.Method = "POST";
            var os = req.GetRequestStream();

            // Add header for JSON part
            string body = "";
            body += "\r\n--" + boundary + "\r\n";
            //body += "Content-Disposition: form-data; name='attachment'\r\n";
            body += "Content-Disposition: form-data; name='entity_content'\r\n";
            body += "Content-Type: application/json\r\n\r\n";

            var doc = new SFAttachment();
            doc.Name = "test";
            doc.ParentId = parentObjectID;  //result.records[0].Id;

            // Add document object data in JSON
            var ser = new JavaScriptSerializer();
            body += ser.Serialize(doc);

            // Add header for binary part             
            body += "\r\n--" + boundary + "\r\n"; 
            body += "Content-Disposition: form-data; name='body'; filename='test.txt'\r\n";
            body += "Content-Type: binary/octet-stream\r\n\r\n";

            // Add header data to request
            byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
            os.Write(data, 0, data.Length);

            // Add file to reqeust
            //FileStream fileStream = new FileStream(fileBrowser.FileName, FileMode.Open, FileAccess.Read);
            FileStream fileStream = new FileStream(@"C:\test.txt", FileMode.Open, FileAccess.Read);
            byte[] buffer = new byte[4096];
            int bytesRead = 0;
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                os.Write(buffer, 0, bytesRead);
            }
            fileStream.Close();

            // Add trailer
            byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
            os.Write(trailer, 0, trailer.Length);
            os.Close();

            // Do the post and get the response.
            WebResponse resp;

            try
            {
                resp = req.GetResponse();
            }
            catch (WebException ex)
            {
                resp = ex.Response;
            }

            var sr = new System.IO.StreamReader(resp.GetResponseStream());

        }


    public class SFAttachment
    {
        public string Id { get; set; }
        public string BodyLength { get; set; }
        public DateTime? LastModifiedDate { get; set; }
        public string Name { get; set; }
        public string Body { get; set; }
        public string ParentId { get; set; }
    }

 
Best Answer chosen by Chad Joubert
Chad JoubertChad Joubert
I was able to figure this out using the new file management content versions:
 
protected async Task LoadDocument(string parentObjectID)
        {
          
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;

            var auth = new AuthenticationClient();
            var url = IsSandboxUser.Equals("true", StringComparison.CurrentCultureIgnoreCase)
                ? "https://test.salesforce.com/services/oauth2/token"
                : "https://login.salesforce.com/services/oauth2/token";

            await auth.UsernamePasswordAsync(ConsumerKey, ConsumerSecret, Username, Password, url);

            string boundary = "----" + DateTime.Now.Ticks.ToString("x");

            var uri = auth.InstanceUrl + "/services/data/v37.0/sobjects/ContentVersion/";

            var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
            req.Headers.Add("Authorization: OAuth " + auth.AccessToken);
            req.ContentType = "multipart/form-data; boundary=" + boundary;
            req.Method = "POST";
            var os = req.GetRequestStream();

            // Add header for JSON part
            string body = "";
            body += "\r\n--" + boundary + "\r\n";
            //body += "Content-Disposition: form-data; name='attachment'\r\n";
            body += "Content-Disposition: form-data; name='entity_content'\r\n";
            body += "Content-Type: application/json\r\n\r\n";

            var doc = new SFContentVersion();
            doc.PathOnClient = fileBrowser.FileName;

            // Add document object data in JSON
            var ser = new JavaScriptSerializer();
            body += ser.Serialize(doc);


            // Add header for binary part             
            body += "\r\n--" + boundary + "\r\n";
            body += "Content-Type: application/octet-stream\r\n";
            body += "Content-Disposition: form-data; name='VersionData'; filename='" + fileBrowser.FileName + "'\r\n\r\n";

            // Add header data to request
            byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
            os.Write(data, 0, data.Length);

            // Add file to reqeust
            FileStream fileStream = new FileStream(fileBrowser.PostedFile.FileName, FileMode.Open, FileAccess.Read);
            byte[] buffer = new byte[4096];
            int bytesRead = 0;
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                os.Write(buffer, 0, bytesRead);
            }
            fileStream.Close();

            // Add trailer
            byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
            os.Write(trailer, 0, trailer.Length);
            os.Close();

            // Do the post and get the response.
            WebResponse resp;

            try
            {
                resp = req.GetResponse();
            }
            catch (WebException ex)
            {
                resp = ex.Response;
                return "Error uploading file.";
            }


            if (resp == null) return null;
            var sr = new System.IO.StreamReader(resp.GetResponseStream());
            return resp.Headers.GetValues("Location").FirstOrDefault();

        }


    public class SFContentVersion
    {
        public string ContentDocumentId { get; set; }
        public string ReasonForChange = "Uploaded from External App.";
        public string PathOnClient { get; set; }
        public string SharingOption = "A";
    }