You are using an older browser that might negatively affect how this site is displayed. Please update to a modern browser to have a better experience. Sorry for the inconvenience!

Step by Step Instructions for Accessing Salesforce Data from .Net Applications


Introduction:

Salesforce integrates with Microsoft .Net applications using Soap API, which lets you access and manipulate Salesforce data and functionality in Force.com cloud platform. This Integration method can be executed on any Microsoft .NET supported platform including but not limited to Windows Desktop Applications, Windows Web Applications. This article provides step-by-step instructions to establish such an integration, which involves the following high level steps:

• Generate API WSDL in Salesforce
• Add web service reference to the .Net application
• Establish API reference within Salesforce

Step 1: Generating API WSDL:

In order for a .NET application to integrate with Force.com, a reference to the SOAP API must be added to the application within Visual Studio. This reference is established through the use of a WSDL file generated from the Force.com platform. A WSDL file is an XML file that describes how a SOAP-based web service functions, how an application can communicate with the web service, and the operations that are allowed within the SOAP API.

WSDL files are retrieved via the standard user interface in a Salesforce organization by logging into and navigating to Setup > Build > Develop > API. Choose the appropriate WSDL and download the file to a location accessible to your development environment.

For example, in the screenshot provided below, click Generate Enterprise WSDL.

dt1.png
Fig1: Generate API WSDL

Copy the URL from Address bar. This URL will be used in the next step.

dt2.png
Fig2: Generated WSDL file

Step 2: Adding a Web Service Reference to an Application:

Access the .Net Application (Desktop or Web) using Visual Studio 2008 or higher version of Visual Studio, for which Salesforce integration is required. In Solution Explorer under your application select the References Folder.

Right Click References Folder and then select the Add Service Reference option.

dt3.png

The steps to add a web reference vary, depending on the edition of Visual Studio used as well as that of the .NET Framework for which the application was developed. Visual Studio 2008 and above now reference ‘Add Service Reference’ to projects and have deprecated the ‘Add Web Reference’ term. Regardless of the version used, steps to add a reference to your WSDL file are one and the same.

Open the add reference dialog box via the ‘Add Service Reference’ or ‘Add Web Reference’ command from the Project menu.

Click the Advanced button.

dt4.png
Fig3: Add Service Reference

dt5.png
Fig4: Add Web Reference

Paste the copied WSDL URL from Step 1 into URL textbox. Click the go button. This will take you to your Salesforce instance.

dt6.png
Fig5: Browsing Web Services

Step 3: Enter your salesforce login details. Click the login button.

dt7.png
Fig6: Adding Web Services

Provide location of WSDL file in order to create the reference. Locations can take multiple forms including HTTP address. In this example, the http address of the WSDL is highlighted in fig5.

Establish name of reference to be used in your application. This is referred to as either the Web reference name or Namespace. This name becomes the established namespace for all references to objects, properties and methods enclosed in the WSDL file.

Enter the Web reference name and click the Add Reference button.

dt8.png

dt9.png
Fig6: Added Web Service

Using the Salesforce API Reference:

A valid username and password must be passed to the API in order to authenticate and establish a secure session with the API. Only then will the .NET application be allowed to interact with the Force.com API and use any functionality or access any data through the Salesforce Force.com platform.

Regardless of the authentication method used, there are security considerations to keep in mind when developing an application:

Session State: All operations, regardless of the chosen authentication method, must be conducted with a valid Force.com session established. Fortunately for .NET developers, all of the necessary legwork is done for you when a Force.com API service is first instantiated. A developer simply needs to capture the pertinent values returned from the Force.com API and consume them appropriately in the application.

Object and Field level permissions: The Force.com SOAP API utilizes the same security framework on which other Force.com applications run. This universal architecture allows a .NET developer to establish the appropriate permissions for both objects (standard and custom) as well as individual fields within the Force.com platform. These permissions will trickle down to a .NET application and prevent any unauthorized operation or permit an allowed operation without any additional programming.

CRUD Operations: Like object and field level permissions, the Force.com security framework controls which CRUD (Create, Read, Update, Delete) operations are permitted for a given object type. Once again, the heavy lifting has already been handled within the Force.com platform, thus removing the need for additional programming.

Login to the Force.com API: Once the username and password values are established, they are passed to the API to determine if they are valid. As part of this validation, a binding to the API is established by instantiating a SforceService object. Once the binding is established, the result of the login attempt is returned in the form of a LoginResult object. Best practices also dictate this login attempt be wrapped in a try catch block to allow for graceful handling of any exceptions that may be thrown as part of the login process.

try {
        	using (SforceService service = new SforceService())
                {                
LoginResult loginResult =  service.login(username,String.Concat(password,securityToken));                    
                    	this.SessionID = loginResult.sessionId;
                    	this.ServerUrl = loginResult.serverUrl;                    
                }

                return true;
     }
catch (Exception exception)
     {
       return false;          }

Establish the Session: Once a successful login has been executed, it is necessary to establish a valid Force.com API session by setting the endpoint URL for your binding object to communicate with as well as set any required values to create a valid session header.

CRUD Operations:

Lead lead = new Lead();
lead.FirstName = “Your FirstName”;
lead.LastName = “Your LastName”;
lead.Email = “Your Email”;
lead.Company=” Your CompanyName”;

Create:

public void Create(Lead lead)
        {
            using (APIHelper api = new APIHelper())
            {
                sObject[] inserts = new sObject[] { lead };
                api.Insert(inserts);
            }
        }

Read:

public List<Lead> Read()
        {
            string soql =
               @"SELECT lead.ID, lead.Email, lead.FirstName, lead.LastName, lead.Company  FROM Lead lead";
            using (APIHelper api = new APIHelper())
            {
                List<Lead> leads = api.Query<Lead>(soql);

               return leads;
            }
        }

Update:

public void  Update(string id, string email)
        {
            Load modifiedLead = new Lead() { Id = id, Email = email };
            using (APIHelper api = new APIHelper())
            {
                sObject[] updates = new sObject[] { modifiedLead };
                api.Update(updates);
            }

        }

Delete:

public void Delete(Lead lead)
        {
            using (APIHelper api = new APIHelper())
            {
                string[] ids = new string[] { lead.Id };
                api.Delete(ids);
            }
         }

There are two common classes used. These class names are 1. ForceConnection.cs 2. APIHelper.cs .

ForceConnection.cs: To authenticate, we have to call the “login” method on an instance of the SforceService while passing the username and password. The password needs to have the security token appended at the end.

public class ForceConnection
   
 {
        public string SessionID { get; set; }
        public string ServerUrl { get; set; }


        public ForceConnection(string username, string password, string securityToken)
        {
            Login(username, password, securityToken);
        }
        
        //login method
        private bool Login(string username, string password, string securityToken)
        {
            try
            {               
                using (SforceService service = new SforceService())
                {                
         LoginResult loginResult = service.login(username, String.Concat(password, securityToken));                    
                    this.SessionID = loginResult.sessionId;
                    this.ServerUrl = loginResult.serverUrl;                    
                }
                return true;
            }
            catch (Exception exception)
            {
                return false;
            }
        }
    }

APIHelper.cs: This class is used for the CRUD Operations.

public class APIHelper : IDisposable
    {
        public static Dictionary<Guid, List<sObject>> asyncResults;

        private SforceService salesforceService;
        const int defaultTimeout = 30000;

        public APIHelper()
        {
            salesforceService = new SforceService();
            salesforceService.Timeout = defaultTimeout;
            asyncResults = new Dictionary<Guid, List<sObject>>();
        }

        public APIHelper(int timeout) : this()
        {
            salesforceService.Timeout = timeout;
        }
        
        //generic query list
        public List<T> Query<T>(string soql) where T : sObject, new()
        {
            List<T> returnList = new List<T>();
            SetupService();
            QueryResult results = salesforceService.query(soql);
            for (int i = 0; i < results.size; i++)
            {
                T item = results.records[i] as T;

                if (item != null)
                    returnList.Add(item);
            }

            return returnList;
        }
        
        //generic query single
        public T QuerySingle<T>(string soql) where T : sObject, new()
        {
            T returnValue = new T();

            SetupService();
             QueryResult results = salesforceService.query(soql);

            if (results.size == 1)
                returnValue = results.records[0] as T;

            return returnValue;
        }

        public Guid QueryAsync(string soql)
        {
            SetupService();
            salesforceService.queryCompleted += salesforceService_queryCompleted;
            
            Guid id = Guid.NewGuid();

            salesforceService.queryAsync(soql, id);

            return id;
        }

        void salesforceService_queryCompleted(object sender, queryCompletedEventArgs e)
        {
            Guid id = (Guid)e.UserState;
            List<sObject> results = e.Result.records.ToList();

            if (asyncResults.ContainsKey(id))
                asyncResults[id].AddRange(results);
            else
                asyncResults.Add((Guid)e.UserState, results);
        }

        //update 
        public SaveResult[] Update(sObject[] items)
        {
            SetupService();

            return salesforceService.update(items);
        }


        //get the urls
        public DescribeSObjectResult[] GetUrls(string[] items)
        {
            SetupService();

      
    DescribeSObjectResult[] describeSObjectResults = salesforceService.describeSObjects(items);
            return describeSObjectResults;
       
        }
        
        //upsert
        public UpsertResult[] Upsert(string externalID, sObject[] items)
        {
            SetupService();
            return salesforceService.upsert(externalID, items);
        }

        //insert
        public SaveResult[] Insert(sObject[] items)
        {
            SetupService();
            SaveResult[] mysaveresult = salesforceService.create(items);
            foreach (SaveResult result in mysaveresult)
            {
                if (result.success != true)
                {
                    
                }
                
            }

            return mysaveresult;

        }
        
        //delete
        public DeleteResult[] Delete(string[] ids)
        {
            SetupService();

            return salesforceService.delete(ids);
        }

        //undelete
        public UndeleteResult[] Undelete(string[] ids)
        {
            SetupService();

            return salesforceService.undelete(ids);
        }


        //Setup service
        private void SetupService()
        {
 ForceConnection connection = new ForceConnection(username, password, securityToken);
            salesforceService.SessionHeaderValue =
                new SessionHeader() { sessionId = connection.SessionID };

            salesforceService.Url = connection.ServerUrl;
        }

        public void  Dispose()
        {
            salesforceService.Dispose();
        }
    }
}