I am trying access the Salesforce API from an external application. I've done the following:

  1. I've gone to the API tab and generated the WSDL.
  2. I then ran the .NET framework's WSDL tool to generate the C# file, which I then added to my C# project.
  3. I then attempted to login in the following manner:

    SforceService binding = new SforceService(); LoginResult result = sfs.login(uid, pwd);

I get an error on the .login method: INVALID_LOGIN: Invalid username, password, security token; or user locked out.

Then I realized that we have single signon enabled on our environment, so that maybe the .login method is unnecesary. So I proceeded without it.

SforceService binding = new SforceService();
var qResult = binding.query("SELECT Name FROM Account");

I got an error on the .query method: UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService.

So I am lost at this point. Is there something simple I am missing?

  • You might haven't set the production/sandbox setting accordingly? If you're trying to authenticate to a sandbox instance, make sure you edit the Properties -> Settings.settings file and change the URL from https://login.salesforce.com/services/Soap/c/XX.X to https://test.salesforce.com/services/Soap/c/XX.X Mar 26 '14 at 22:31

I had the wrong username, but there was actually more to it. I had to reset session ID and server URL.

Here is the way to do it, so that others can benefit.

bool done = false;

var binding = new SforceService();
LoginResult result = binding.login("user@foo.bar", "password");

binding.Url = result.serverUrl;
// The line below is what I've missed
binding.SessionHeaderValue = new SessionHeader {sessionId = result.sessionId};

var queryResults = binding.query("SELECT Name FROM Account");

if (queryResults.size > 0)
    Debug.WriteLine("Logged-in user can see a total of " + queryResults.size + " accounts.");
    while (!done)
        sObject[] records = queryResults.records;
        for (int i = 0; i < records.Length; ++i)
            var con = (Account)records[i];
            Debug.WriteLine("Account " + (i + 1) + ": " + con.Name);

        if (queryResults.done)
            done = true;
            queryResults = binding.queryMore(queryResults.queryLocator);
  • Ah yes, you always need to replace the session header, every time you authenticate it gives you a different one so you were probably using an expired session id. Please accept your own answer Mar 27 '14 at 1:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.