Saturday, October 30, 2010

Salesforce.com REST API


A while back I had the opportunity to develop a .NET desktop application that interfaced to Salesforce.com using the SOAP API, so I was very interested when I heard about SFDC's new REST based API. The beta of this interface has just been made available to developers and will eventually go into production in a future release. SFDC has made a simple Java sample available but no .NET samples yet, so I thought I would write an article explaining how to access the API from .NET. This example will be done in C# using Visual Studio 2010 and the .NET Framework 4.0 although there is no reason this couldn't be done with earlier versions of the framework.
To try out the API you will need a Salesforce.com developer account. You can sign up for a free account at http://developer.force.com/. I am not sure if the REST API is automatically enabled for all developer accounts, but if not you can sign up for it here.

Authentication

Before you can use the REST API you need to authenticate to Salesforce.com. There are two ways to do this, using a Session ID from the old SOAP API, or using OAuth which is what I will be doing in this sample. OAuth allows an application to access a web based resource without the user having to provide their login details to the calling application. The exact details of how OAuth works are beyond the scope of this article but you can learn more at ouath.net.
The first step in authentication is to enable the REST interface. To do this log into your SFDC account and select Setup. Under App Setup, select Develop then Remote Access, this will display a list of Remote Access Applications. The list will be empty at this point, so click on New to add a new remote access application.
clip_image002
There are two required fields, the Application name which can be anything of you choosing, and the Callback URL which needs a little explanation. OAuth is primarily designed to be used between two web sites. The web site requesting access will redirect to the SFDC login screen, and when the user has logged in the SFDC web site will re-direct back to the Callback URL you specify. If you are developing a web application this needs to be the URL of a secure (HTTPS) page. In this demo, since we are developing a desktop app, we don’t want to actually redirect so we put in an identifier of our choice that we will catch in our application.
Once you have filled out the form, click Save, then click on the application name on the list. The details you entered will be re-displayed along with the Consumer Key and Consumer Secret which we will need during the authentication process. I created some object level variables to hold this information:
private string clientID = “YOUR CONSUMER KEY";
private string clientSecret = “YOUR CONSUMER SECRET";
private string redirectURL = "resttest:callback";

Since the key and secret are specific to my SFDC account I have omitted them in the demo. You will need to put in the ones from your account.

The next thing we need to do is have our application call the SFDC login page. If this was a web app we could simply re-direct to is, but since this is a desktop app we can use the WinForms WebBrowser control. I added a WebBrowser control to my form and then put the following code in the Form_Load event:

var authURI = new StringBuilder();
authURI.Append("https://login.salesforce.com/services/oauth2/authorize?");
authURI.Append("response_type=code");
authURI.Append("&client_id=" + clientID);
authURI.Append("&redirect_uri=" + redirectURL);
webBrowser1.Navigate(authURI.ToString());



First we build a URL that points to the SFDC login page and includes the Consumer Key (called client_id) and the re-direct URL as query strings. Next we call Navigate on the web browser control to point to this location.
Once the user has entered their credentials using the web browser control it will be re-directed to resttest:callback. We can catch this in the webBrowser_DocumentCompleted event handler:

if (e.Url.AbsoluteUri.StartsWith("resttest:callback"))
{
webBrowser1.Navigate("about:blank");
code = e.Url.Query;
code = code.Substring(6);

GetToken();
}

When the redirect is found the first thing I did was redirect the web browser control to a blank page. This is not necessary but it looks nice. The URL that is returned will look like this:

callback?code=aPrx9vip.t4qSZdAs_DHNIR9mEcerAoVsq.hX9qVAtUNfAibMV8ClSmYxbsxiWb81O8BzgRwLA%3D%3D

We need to get the code query string since this is needed for the next part of the authentication process. The code is only valid for a short time so we need to use it to get an access token which is what we will actually use to do the REST calls. Here is the code to get the token:
private void GetToken() {
string URI = "https://login.salesforce.com/services/oauth2/token";
StringBuilder body = new StringBuilder();
body.Append("code=" + code + "&");
body.Append("grant_type=authorization_code&");
body.Append("client_id=" + clientID + "&");
body.Append("client_secret=" + clientSecret + "&");
body.Append("redirect_uri=" + redirectURL);

string result = HttpPost(URI, body.ToString());

}

This time instead of passing the parameters as query string we will pass them in the body of the post. You can see that we add parameters for the code returned in the last step, the clinet_id (Consumer Key), client_secret (Consumer Secret) and redirect_uri, then call an HttpPost. The HttpPost is simply a wrapper function around a System.Net.WebRequest object. You can see the full code in the download.

The result returned from the post will be the JSON encoded authentication data:

{
\"id\":\"https://login.salesforce.com/id/0axD7230dz0xrrP/x0e7f0D0A039F1y\",
\"issued_at\":\"1288375889300\",
\"refresh_token\":\"5APp8axZfY11MvXxUzgcRXyJ6zGtoLbD66hgHfx97d9Vklp7uFRmB6minfJwRJr_Ea4Zh563C0s_eg==\",
\"instance_url\":\"https://na5.salesforce.com\",
\"signature\":\"W11FfBhvQ1kwXvNsNTas+Gn3812XRmPL2utxxKbEqss=\",
\"access_token\":\"K0DT029060yJrrP!AR4AQJMczwx9435JeGyhsY40M.OM1BJo5c72z9Hb.F6T5lvqX992pt0KPabj8Snx7L1CqaKxUi7wixxcnfIa9UDY1KiXl0fb1\"

}

If you are using .NET Framework 3.5 or 4, the easiest way to parse this is to use a JavaScriptSerializer call from the System.Web.Script.Serialization namespace. First I created a class to put the data into.

public class TokenResponse
{

public string id { get; set; }
public string issued_at { get; set; }
public string refresh_token { get; set; }
public string instance_url { get; set; }
public string signature { get; set; }
public string access_token { get; set; }

}

Then we can use the following code to parse the response. This will convert the JSON into an instance of the TokenResponse class.

JavaScriptSerializer ser = new JavaScriptSerializer();
token = ser.Deserialize<TokenResponse>(result);

Now the authentication process is complete, so we can actually use this token to call a REST function. We start with a wrapper function that does an HTTP GET.

public string HttpGet(string URI, string Parameters)
{

System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
req.Method = "GET";
req.Headers.Add("Authorization: OAuth " + token.access_token );
System.Net.WebResponse resp = req.GetResponse();

if (resp == null) return null;
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();

}

You will notice that I am adding the access_token we got in the last step as the Authorization header. To actually call this routine we do the following:

string s = HttpGet(token.instance_url + @"/services/data/v20.0/", "");

We are doing the get using the instance URL returned in the last step, and calling the REST function “/services/data/v20.0/”. This will return a list of the available REST resource and will look something like this:

{
"sobjects":"/services/data/v20.0/sobjects",
"search":"/services/data/v20.0/search",
"query":"/services/data/v20.0/query",
"recent":"/services/data/v20.0/recent"
}

So there are the basics of how to get started with the SFDC REST API. You can download the full code in a Visual Studio 2010 here:

Visual Studio 2010 Salesforce REST API Demo

You can find more information on the Developerforce web site:

Getting Started with the Force.com REST API (Java)

REST API Resource Page

REST API Documentation