Connect to the Salesforce SOAP API in .Net

C# and the Salesforce Partner API

In general the Salesforce API documentation is excellent but I found the sample code for connecting via C# to be unhelpful at best. So here’s a full guide to connecting to the Salesforce Partner API in C# and dot Net. I’ve used Visual Studio 2017 in these examples.

Salesforce Partner API WSDL and User Token

First you need to download the Partner WSDL file from your Salesforce instance. Find the API WSDL and generate the Partner WSDL. Save the resulting xml file somewhere accessible:

Generate the Salesforce Partner API WSDL file

In Visual Studio create a new C# console app targeting .net framework 4.6 or higher. This is to ensure TLS 1.2 is used as TLS 1.0 is not supported by the Salesforce API. Next add a service reference for the Partner WDSL. Right click on the solution and select Add -> Service Reference.

Add a service reference for a WSDL file in Visual Studio

In the address add the path to the Partner WDSL that you downloaded above and specify a Namespace for the service and hit OK.

Add a service reference for a WSDL file in Visual Studio

As well as adding the service this will add the Salesforce login endpoint to the App.config file:

    <system.serviceModel>

      <bindings>
        
          <basicHttpBinding>
            <binding name="SoapBinding" maxReceivedMessageSize="8048576">
              <security mode="Transport" />
            </binding>
          </basicHttpBinding>
          
        </bindings>
  
      
      <client>

        <endpoint address="https://login.salesforce.com/services/Soap/u/42.0"
                  binding="basicHttpBinding" bindingConfiguration="SoapBinding"
                  contract="sf_partner.Soap" name="Soap" />

      </client>

    </system.serviceModel>

Note that the maxReceivedMessageSize is far too small by default so you’ll want to set it explicitly using the attribute in the binding node as show above. If a message exceeds this size you get the following exception:

The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

You also need your Security Token which you can regenerate if required:

Regenerate Salesforce User Security Token

Login to the Salesforce Partner API

Connecting to the required SF instance is a two step process. First you connect to the login endpoint. If this is successful it provides an endpoint for the actual SF instance to connect to. Add this code to the Main class:

using System.ServiceModel;
using SFP = SFAPI.sf_partner;

        static void Main(string[] args)
        {
            string User = "myUser";
            string Password = "myPassword";
            string Token = "myToken";
            EndpointAddress SFEndpointAddress;

            SFP.SessionHeader SFSessionHeader;
            SFP.SoapClient SFSoapClient;
            SFP.SoapClient sc = new SFP.SoapClient();
            SFP.LoginResult lr = sc.login(null, null, User, Password + Token);
            SFEndpointAddress = new EndpointAddress(lr.serverUrl);
            SFSessionHeader = new SFP.SessionHeader();
            SFSessionHeader.sessionId = lr.sessionId;
            sc.Close();
            SFSoapClient = new SFP.SoapClient("Soap", SFEndpointAddress);

        }

When the SOAP client is created without parameters (new SFP.SoapClient()) the login endpoint is taken from the App.config file.

        <client>
            <endpoint address="https://login.salesforce.com/services/Soap/u/51.0"
                binding="basicHttpBinding" bindingConfiguration="SoapBinding"
                contract="sf_partner.Soap" name="Soap" />
        </client>

If the login is successful the login results include the endpoint address for the instance to connect to. This is used to create a SOAP client targeting the actual instance:

new SFP.SoapClient("Soap", SFEndpointAddress);

All calls to the API require a SessionHeader with a SessionId which is also provided by the login result:

SFSessionHeader = new SFP.SessionHeader();
SFSessionHeader.sessionId = lr.sessionId;

Run this for your user, password and token credentials and it will fail and you’ll get an error similar to this:

error CS0030: Cannot convert type 'SFAPI.sf_partner.ListViewRecordColumn[]' to 'SFAPI.sf_partner.ListViewRecordColumn'

error CS0029: Cannot implicitly convert type 'SFAPI.sf_partner.ListViewRecordColumn' to 'SFAPI.sf_partner.ListViewRecordColumn[]'

This is because of an error in the WSDL definition. Whether this is Saleforce or .Net issue I don’t know but it can be fixed by editing the service reference.cs file. In your project open Connected Services -> sf_partner and open the reference.cs file.

Amend a Web Service reference.cs file in Visual Studio

Find these two lines and remove the second set of brackets from the type definitions:

private ListViewRecordColumn[][] recordsField;
public ListViewRecordColumn[][] records {

becomes…

private ListViewRecordColumn[][recordsField;
public ListViewRecordColumn[] records {


The code above should run fine now. That resolves the various connection issues. Here’s how to run a simple SOQL query.

Execute Query against Salesforce SOAP API

Add the following to the Main class:

string select = "select Name from Account";
SFP.LimitInfo[] li;
SFP.QueryResult qr = null;

li = SFSoapClient.queryAll(SFSessionHeader, null, null, select, out qr);

Console.WriteLine(qr.records[0].Any[0].InnerText);
Console.ReadLine();

I’m using the queryAll method to return the results of the SOQL query in the string select. The results are returned in the QueryResult object. This includes a collection of returned sObject records. Here I’m returning the first field value from the first record returned.

Obviously there’s a lot more to using the API but this should at least get you connected successfully in a .Net environment. Since it also has some similar issues in .Net I’ve posted how to connect to the Saleforce Metadata API as well.