Wade Wegner, a friend of the blog and an evangelist for Salesforce.com, just built a new .NET Toolkit for Salesforce developers. This Toolkit is open source and available on GitHub. Basically, it makes it much simpler to securely interact with the Salesforce.com REST API from .NET code. It takes care of “just working” on multiple Windows platforms (Win 7/8, WinPhone), async processing, and wrapping up all the authentication and HTTP stuff needed to call Salesforce.com endpoints. In this post, I’ll do a basic walkthrough of adding the Toolkit to a project and working with a Salesforce.com resource.
After creating a new .NET project (Console project, in my case) in Visual Studio, all you need to do is reference the NuGet packages that Wade created. Specifically, look for the DeveloperForce.Force package which pulls in the “common” package (that has baseline stuff) as well as the JSON.NET package.
First up, add a handful of using statements to reference the libraries we need to use the Toolkit, grab configuration values, and work with dynamic objects.
using System.Configuration; using Salesforce.Common; using Salesforce.Force; using System.Dynamic;
The Toolkit is written using the async and await model for .NET, so calling this library requires some knowledge of this. To make life simple for this demo, define an operation like this that can be called from the Main entry point.
static void Main(string[] args) { Do().Wait(); } static async Task Do() { ... }
Let’s fill out the “Do” operation that uses the Toolkit. First, we need to capture our Force.com credentials. The Toolkit supports a handful of viable authentication flows. Let’s use the “username-password” flow. This means we need OAuth/API credentials from Salesforce.com. In the Salesforce.com Setup screens, go to Create, then Apps and create a new application. For a full walkthrough of getting credentials for REST calls, see my article on the DeveloperForce site.
With the consumer key and consumer secret in hand, we can now authenticate using the Toolkit. In the code below, I yanked the credentials from the app.config accompanying the application.
//get credential values string consumerkey = ConfigurationManager.AppSettings["consumerkey"]; string consumersecret = ConfigurationManager.AppSettings["consumersecret"]; string username = ConfigurationManager.AppSettings["username"]; string password = ConfigurationManager.AppSettings["password"]; //create auth client to retrieve token var auth = new AuthenticationClient(); //get back URL and token await auth.UsernamePassword(consumerkey, consumersecret, username, password);
When you call this, you’ll see that the AuthenticationClient now has populated properties for the instance URL and access token. Pull those values out, as we’re going to use them when interacting the the REST API.
var instanceUrl = auth.InstanceUrl; var accessToken = auth.AccessToken; var apiVersion = auth.ApiVersion;
Now we’re ready to query Salesforce.com with the Toolkit. In this first instance, create a class that represents the object we’re querying.
public class Contact { public string Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
Let’s instantiate the ForceClient object and issue a query. Notice that we pass in a SQL-like syntax when querying the Salesforce.com system. Also, see that the Toolkit handles all the serialization for us!
var client = new ForceClient(instanceUrl, accessToken, apiVersion); //Toolkit handles all serialization var contacts = await client.Query<Contact>("SELECT Id, LastName From Contact"); //loop through returned contacts foreach (Contact c in contacts) { Console.WriteLine("Contact - " + c.LastName); }
My Salesforce.com app has the following three contacts in the system …
Calling the Toolkit using the code above results in this …
Easy! But does the Toolkit support dynamic objects too? Let’s assume you’re super lazy and don’t want to create classes that represent the Salesforce.com objects. No problem! I can use late binding through the dynamics keyword and get back an object that has whatever fields I requested. See here that I added the “FirstName” to the query and am not passing in a known class type.
var client = new ForceClient(instanceUrl, accessToken, apiVersion); var contacts = await client.Query<dynamic>("SELECT Id, FirstName, LastName FROM Contact"); foreach (dynamic c in contacts) { Console.WriteLine("Contact - " + c.FirstName + " " + c.LastName); }
What happens when you run this? You should have all the queried values available as properties.
The Toolkit supports more than just “query” scenarios. It also works great for create/update/delete as well. Like before, these operations worked with strongly typed objects or dynamic ones. First, add the code below to create a contact using our known “contact” type.
Contact c = new Contact() { FirstName = "Golden", LastName = "Tate" }; string recordId = await client.Create("Contact", c); Console.WriteLine(recordId);
That’s a really simple way to create Salesforce.com records. Want to see another way? You can use the dynamic ExpandoObject to build up an object on the fly and send it in here.
dynamic c = new ExpandoObject();// c.FirstName = "Marshawn"; c.LastName = "Lynch"; c.Title = "Chief Beast Mode"; string recordId = await client.Create("Contact", c); Console.WriteLine(recordId);
After running this, we can see this record in our Salesforce.com database.
Summary
This is super useful and a fantastic way to easily interact with Salesforce.com from .NET code. Wade’s looking for feedback and contributions as he builds this out further. Add issues if you encounter bugs, and issue a pull request if you want to add features like error handling or support for other operations.
Hi,
Its fantastic way to connect to Salesforce.
The above code is only working in console Application not on web Application. Could please shed some light on it.
Thanks & Regards !!!
Inderpal Singh Uppal
Hey there. Make sure you wire it up properly depending on your web framework. For instance, for ASP.NET Web Forms, make sure the page is marked as Async, and that you register the async method http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45
Thank you so much for this! Saved me a lot of time.
Could you please tell, how to access a custom app using this.
Not sure if that’s supported yet!
I have tries a lot but it is not able to integrate it with it.
Is there any other way of accessing the custom apps from salesforce to the .Net
Yes. I wrote up an article that shows how to consume custom REST services (http://wiki.developerforce.com/page/Working_with_Custom_SOAP_and_REST_Services_in_.NET_Applications) and standard ones (http://wiki.developerforce.com/page/Consuming_Force.com_SOAP_and_REST_Web_Services_from_.NET_Applications)
I’ve been trying this as well (from both VB.net and C#.net projects) but I cannot seem to connect to my SANDBOX environment. I keep this exception: “Salesforce.Common.ForceException: expired access/refresh token”.
I have revoked/refreshed my personal security token, but it doesn’t seem to help.
When I follow the older instructions (which use the old HTTPClient/Dictionary combo) I can successfully log in.
Anybody else having that issue? Perhaps I am missing something in my setup.
nevermind – I figured out my issue. I was not passing in the proper tokenRequestEndpointURL for a sandbox environment during the username/password authentication flow.
Glad you got it! Thanks for sharing the resolution.
Hi Thomas,
What did you use for the tokenRequestEndpointURL? I am getting the same error and am unable to resolve it.
How do you query more than 2000 records using this toolkit?
I don’t think you can. I thought the API supported a paging token, but not sure if the toolkit returns this to you. Sounds like a good item for the Github issues list!
Can you do a similar sample for WebServerOAuthFlow? The GIThub sample (https://github.com/developerforce/Force.com-Toolkit-for-NET/tree/master/samples/WebServerOAuthFlow) for this doesn’t seem to work; I am not able to get the AccessToken.
When this line is called
await authentication.UsernamePasswordAsync(“consumer_key”, “consumer_secret”, “username”, “password”);
I get Salesforce.Common.ForceAuthException with message “authentication failure – Failed: API security token required”
Any ideas why this is happening? How can this be fixed?
Hmm. Are you sure you’re passing in all the valid credentials? Have you set up an “application” in SFDC to get the consumer key and secret?
Yes, all credentials I am passing are correct. If I pass invalid credentials, it throws a different error saying something like “Invalid Credentials”
I have a Connected App that I am using for this. Should I be using something else?
Is there also a possibility that the async code has moved on and is trying to call the REST endpoint BEFORE the auth token has returned?
No, I have breakpoints on every line in the code, it throws an error on the above mentioned line without getting to another line of code.
Wade’s suggestion is to make sure that your IP isn’t blocked, and to use the security token http://www.wadewegner.com/2013/11/forcecom-token-requests-with-python/
Remember that the “password” must contain the password + token.
Hi Scott,
Is the password a user’s password in sales force? Also, what token are you referring to and how do we get a hold of that?
What are you supposed to use as the tokenRequestEndpointUrl when you are connecting to a sandbox org ?
I am currently getting a ForceAuthException stating expired access/refresh token no matter what I do..
I have reset my security token twice with no effect…
Thanks,
Greg
Hmm. Not sure about that. Maybe create a Github issue (https://github.com/developerforce/Force.com-Toolkit-for-NET/issues) so that it can be addressed by the toolkit developers.
when connecting to salesforce the tokenRequestEndpointUrl is https://login.salesforce.com/services/oauth2/token. When connecting to the salesforce sandbox it’s https://test.salesforce.com/services/oauth2/token. Your call to UsernamePasswordAsync() should look like this
await auth.UsernamePasswordAsync(_consumerKey, _consumerSecret, _username, _password + _passwordSecurityToken, _userAgent, _tokenRequestEndpointUrl);
the _userAgent string can be set to “common-libraries-dotnet”
here’s a link to the AuthenticationClient.cs class
http://www.symbolsource.org/Public/Metadata/NuGet/Project/developerforce.common/0.3.1/Release/Default/Salesforce.Common/Salesforce.Common/AuthenticationClient.cs?ImageName=Salesforce.Common
Oh my sweet Jesus, thank you! A million thank you’s. You saved my bacon big time here!
is there a way to use dyanmic with queryById?
Hi Richard,
Great post. It helped me to do a benchmark test of the new toolkit compared to the old API. I am sure you will not be surprised to hear that the new method is much faster (duh). The results were published on my blog here: http://saramorgan.net/2014/04/22/comparing-the-force-com-soap-api-to-the-new-salesforce-toolkit-for-net/
I saw that! Great to prove something I was thinking but hadn’t tried.
I’m trying to create a REST service that is used by this salesforce toolkit, but while debugging in visual studio works, when published on IIS I got an error message SalesforceRestService.Lead.d__3.MoveNext(),
The issue was fixed, this is a message generated by Net Framework not by the Salesforce Toolkits for .NET
Hi Richard
I’m trying to create a REST service that is used by this salesforce toolkit, but while debugging in visual studio works, when published on IIS I got an error message SalesforceRestService.Lead.d__3.MoveNext(),
Hi – I’m having an issue where when I call auth.UsernamePasswordAysnc…it just never comes back from that call – any ideas?
Any chance it’s an async issue where your code moves on and you don’t catch the callback?
I don’t think so – the code works fine in a console app…as part of a web page or a webapi (my ultimate goal), no dice…
Remember that web apps need to be prepped for async by adding the Page attribute and registering your operation for async.
Thank you for the response. I did that, and I still had the issue. Also, I’m ultimately more concerned with getting this working as part of a WebAPI, which is producing the same result.
Upon further review – I do not have this issue with a console app…however I’m trying to create my own webapi app that utilizes the methods of this toolkit, and it seems that I run into issues when creating a class that uses these objects that is utilized by my webapi. I also created a simple web form, and I ran into the same issues.
Hi, any luck ? I just tried the same, works great in console app but it does not in the web app, I have also made the following changes to make the it async: the page Async=”true” and RegisterAsyncTask(new PageAsyncTask(RunSample)); in the Page_Load but it just times out
Hi, just tried to test this sample code and am running into a couple of issues. First, the ForceClient object doesn’t appear to have a Query method, but it has a QueryAsync method. So when I tried that, I get a compile error telling me that the contacts returned by this method “does not contain a public definition for ‘GetEnumerator'”.
Any suggestions appreciated.
Shortly after posting, I discovered the answer:
foreach (Contact c in contacts.records)
{ … }
My tutorial on accessing Salesforce data from .Net using a Windows Phone app was recently published on Wrox at http://blogs.wrox.com/article/accessing-salesforce-data-from-a-windows-phone-app/
I cannot install the packes. I receive this error message. Can somebody help me with this?
Install-Package : Unable to read package from path ‘Microsoft.Bcl.1.1.9.nupkg’.
At line:1 char:16
+ Install-Package <<<< DeveloperForce.Force
+ CategoryInfo : NotSpecified: (:) [Install-Package], InvalidDataException
+ FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand
var contacts = await client.Query(“SELECT Id, LastName From Contact”);
On this line i am getting following error:
“The requested resource does not exist”
Did you found any solution for this? even I am facing same error
hi richard, the same code is working well and good for me. how to fetch records from the attachment object and create those attachments using this method? with attachment, it is not working for me.. Could you please advise me a code example. Thanks
Is it possible to authentication with sessionId instead of ( without consumer key,consumerSecret / UserName, password)?
Hello, Could you tell how to access entities metadata?
Having trouble using this toolkit when deploying my app to IIS. Locally everything works perfectly but once deployed to our dev server I am getting the following error when querying salesforce:
Could not load type ‘d__7`1’ from assembly ‘Salesforce.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f7864e53fb79388’ due to value type mismatch.
Any help would be greatly appreciated.
Hi Richard,
Can you please guide how we can use this SDK to convert lead into account
Thanks
Raghav
Hi, I am new to Powershell and Salesforce, and I have been looking for ways to query Salesforce objects directly from within Powershell but with no luck so far, and this toolkit definitely offers a lot of what I have been looking for quite some time. Can anyone tell me if there is a way to use the Toolkit in Powershell? Thanks in advance.
Hi Richard,
I’m getting an Error “Task was cancelled” while fetching up to 75000 records.
Could you Please Look into it.
Any help would be greatly appreciated.
Hi Amit. It’d be good to add this to the GitHub project’s issue list (https://github.com/developerforce/Force.com-Toolkit-for-NET). That’s a lot of records for one request, so there’s a chance you’re bumping into natural SFDC API call limits. It might be good to batch up your requests.
Thanks a ton!.
🙂
What message will return SF if token expires? var contacts = await client.Query(“SELECT Id, LastName From Contact”);
You should update the article to comply with the new salesforce requirement to use
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; before making any call to salesforce. The library doesn’t do it so the call fail. It’s not huge but it took me quite some time to find out (and i think it should have been fixed in the library but they don’t seems to want to fix it)
Hello, do you know why this solution does not work in .net web api project? In console application it works great, but in web api controller it hangs on that line:
await auth.UsernamePasswordAsync(consumerkey, consumersecret, username, password, url);
Super lazy? Bro there’s thousands of properties, who in their right mind would recreate all the classes/properties/relationships. Why aren’t they offering a library with all the DTOs in there?
{“The requested resource does not exist”}
Can you shed any light?
This is when attempting to access the object “ServiceAppointment” which is part of Field Services Lighting package. So my client connects just fine and can select data from other objects, like Account, but when I try to do a select on “ServiceAppointment” – I get the error above.