Saturday, April 1, 2023

C# coding : Download Salesforce attachment to local disk using SOAP webservice Enterprise wsdl method (with SOQL selection)

Pre-requisite :

  • Select Target framework to 4.5.2 
  • Install DeveloperForce.Force 2.1.0 (via nuget if VS2015 is used)
  • Import Enterprise wsdl as WebReference (for easy Type Casting , partner wsdl also work but need more code lines.)
  • Update 2 ListViewRecordColumn[][] in Reference.cs to ListViewRecordColumn[].
    Otherwise, error  as below will be shown :
    Cannot convert type 'SaleForceBase.SaleForceRef.ListViewRecordColumn[]' ...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Salesforce;
using System.IO;
using ConsoleApplication1.SfService;

namespace ConsoleApplication1

{
    class Program
    {
        static void Main(string[] args)
        {

            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3 | System.Net.SecurityProtocolType.Tls12;//Added to fix he request was aborted could not create ssl/tls secure channel.

            //Get Salesforce credentials
            var username = "your_salesforce_username";
            var password = "your_salesforce_password";
	   //var token = "your_salesforce_security_token";//uncomment this if you have enabled security token function. 

            var authEndpoint = "https://login.salesforce.com/services/Soap/u/50.0";

            // Login to Salesforce using SOAP API

            var binding = new SforceService();

            try {

            var loginResult = binding.login(username, password);
	    //var loginResult = binding.login(username, password + your_salesforce_security_token); //use this instead of above to login if you have enabled security token function. 
            binding.Url = loginResult.serverUrl;
            binding.SessionHeaderValue = new SessionHeader { sessionId = loginResult.sessionId };

            // Query for to get 5 attachments related to Account object

            var attachmentQuery = "SELECT Id, Name, ParentId FROM Attachment WHERE Parent.Type = 'Account' ORDER BY ParentId limit 5";
            var queryResult = binding.query(attachmentQuery);

            // Loop through the results and download each attachment

            foreach (var sObject in queryResult.records)

            {

                var attachment = (Attachment)sObject;//retrieve(string fieldList, string sObjectType, ID ids[]);
                var account = (Account)binding.retrieve("Name", "Account", new string[] { attachment.ParentId })[0];//returned as sObject[] , so need to get [0] 

                // Create a file name for the attachment

                var fileName = $"{account.Name} - {attachment.Name}";

                // Download the attachment

                var attachmentBody = (Attachment)binding.retrieve("Body" ,"Attachment",  new string[] { attachment.Id })[0];
                File.WriteAllBytes(fileName, attachmentBody.Body);
				
            }
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Error : " + ex.InnerException);
                System.Diagnostics.Debug.WriteLine("Error2 : " + ex.StackTrace);
                System.Diagnostics.Debug.WriteLine("Error3 : " + ex.Message);
            }
        }
    }
}

 

Next year SF migration plan : moving out customer account to AWS , and call SF data with service account

 πŸ‘€ The most challenging part is about those function with user verification. My service cloud with MIAW chat , nearly redo due to the user ...