Showing posts with label Salesforce. Show all posts
Showing posts with label Salesforce. Show all posts

Sunday, September 22, 2013

Salesforce REST Exceptions

I get a lot of emails from people working with the Salesforce REST who say that they are getting a 400 error (Bad Request) when trying to perform one of the API functions. In this article I will talk about this error and how to troubleshoot it as well as other API errors.
For the purpose of this article I will assume you are using an HttpWebRequest object to make your requests to Salesforce. The function on HttpWebRequest that does the actual work is  GetResponse. This function makes the call to the remote server and retrieves the response. If anything goes wrong with a REST API request on the Salesforce server it will generate an 400 HTTP error response code and then GetResponse will throw a WebException containing that status code. The 400 response code isn’t too useful since there are a lot of things that can cause it, but if you catch the exception you can still access the response stream which will contain a JSON object with more details.
As an example, if we make a call to get an Access Token and pass an incorrect client_secret you will get this web exception:
"The remote server returned an error: (400) Bad Request."
If we then get the response stream we find this:
{\"error\":\"invalid_client\",\"error_description\":\"invalid client credentials\"}
Here is another example. If we issue a query command with a syntax error in the SOQL query (SELEC id,accountNumber,name from account), you will get this:
{ \"message\" : \"unexpected token: SELEC\",\n  \"errorCode\" : \"MALFORMED_QUERY\"}
You can see that it didn’t recognize “SELEC” since it is missing the ‘T’. Note that the format of the JSON in this message is different then the first one.
So what is the best way to handle this? There are a number of options depending on you needs, but here is one suggestion. Here is the piece of code that makes the web request that would be in a library used by all Salesforce REST calls. ‘req’ is  a HttpWebRequest object.

req.Method = "GET";
System.Net.WebResponse resp = null;
try
{
    resp = req.GetResponse();
}
catch (WebException ex)
{
    string msg = "";

    if (ex.Status == WebExceptionStatus.ProtocolError)
    {
        resp = ex.Response;
        msg = new System.IO.StreamReader(resp.GetResponseStream()).ReadToEnd().Trim();
    }

    throw new SalesforceException(msg, ex);
}


In the try block we make the call to Salesforce and get the response. Next we catch only WebExceptions, other exceptions are allow to percolate up to the next level which is a good practice for library functions. Next we check that status of the WebException. There are a lot of things that can cause WebExceptions but most of them will result in a response not being returned, so we just look for a ProtocolError. If we do have a protocol error we retrieve the JSON error message from the response. Finally we create and throw a custom exception I call SalesforceException that will hold both the JSON message and the original exception in the InnerException. The code for the SalesforceExpcetion is here:


public class SalesforceException : Exception 
{
    public SalesforceException(string message, Exception innerException)
        : base(message, innerException) { }
}


One other thing to note about Salesforce REST errors. Since REST commands are based on URIs, if you have an error in the URI you will normally get back a HTTP 404 error instead of a 400 error. For example if we send a read command with an invalid object ID in the URI, we will get a 404 error instead of a 400 error.

Sunday, December 2, 2012

Windows 8 + Salesforce.com Part 4

Over the past three posts I have shown how to build a Windows 8 Windows Store Application that will display the Account records from Salesforce.com. As the application is currently built the user needs to login to Salesforce each time it is run. In this post I will show how to keep the use logged in using a refresh token.
Before I continue  a note about the architecture of this demo. I had originally planned to build this using the Model-View-ViewModel (MVVM) design pattern which is very common to XAML applications, but decided for the sake of simplicity to just do a basic event driven architecture for now. At a later date I might do some posts on how to change this into an MVVM based application.
Ok, now on to the updates we are going to make to the program from Part 3. First we need to add a function to sfdcLibrary.cs to get an access token given a refresh token.

public async Task<bool> RefreshToken(string refreshToken)
{
    string URI = "https://login.salesforce.com/services/oauth2/token";
    StringBuilder body = new StringBuilder();

    body.Append("refresh_token=" + refreshToken + "&");
    body.Append("grant_type=refresh_token&");
    body.Append("client_id=" + clientID + "&");
    body.Append("client_secret=" + clientSecret + "&");
    body.Append("redirect_uri=" + redirectURL);
    var response = await HttpPost(URI, body.ToString());

    if (response.StatusCode != System.Net.HttpStatusCode.OK) return false;

    var data = await response.Content.ReadAsStringAsync();
    AccessToken = Deserialize<TokenResponse>(data);

    return true;
}

This function works just like the one we used to get the initial access token, but this one starts from a refresh token and uses that to get the access token. We are also going to change the AccessToken to a public property since we will need to reference it outside of the class.

public TokenResponse AccessToken { get; set; }

Now lets modify AccountsView.xaml to include a UI to login and logout.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
    <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource AppName}" IsHitTestVisible="false" Style="{StaticResource PageHeaderTextStyle}"/>
    <StackPanel Grid.Column="2" Orientation="Vertical" Margin="10,10,10,10" >
        <Button Name="UILogout" HorizontalAlignment="Center" Click="UILogout_Click">Logout</Button>
        <Button Name="UILogin" HorizontalAlignment="Center" Click="UILogin_Click">Login</Button>
        <CheckBox Name="UIStayLoggedIn" HorizontalAlignment="Center">Stay Logged In</CheckBox>
    </StackPanel>
</Grid>

This is the XAML markup for the gird that forms the header of the page. I have added a third column to the grid to hold the controls. I also added a StackPanel with a Login button, Logout button and a check box to control whether the application should stay logged in or not.

To MainPage.xaml.cs we are going to add two functions to control the UI state.

private async void LoggedIn()
{
    UILogin.Visibility = Visibility.Collapsed;
    UIStayLoggedIn.Visibility = Visibility.Collapsed;
    UILogout.Visibility = Visibility.Visible;
    var acc = await App.SFDC.ReadAccounts();
    model.Accounts = acc.records;
}

This function sets the form to a logged in state. The UILogin and UIStayLoggedIn controls are hidden, UILogout control shown and the viewmodel loaded with a list of accounts. You will notice that in XAML Visibility isn’t just a Boolean, it actually has three states. Visible displays the controls, Hidden hides the control but still reserves space for it in the UI and Collapsed hides it and doesn’t reserve space for it. The second function is similar and sets a logged out state.


private void LoggedOut()
{
    UILogin.Visibility = Visibility.Visible;
    UILogout.Visibility = Visibility.Collapsed;
    UIStayLoggedIn.Visibility = Visibility.Visible;
    model.Accounts = null;
    App.SFDC.AccessToken = null;
}

Again we set the control visibility, clear the accounts from the model and clear the access token.  Next we need to change the LoadState function.


protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    LoggedOut();

    this.DataContext = model;

    if (ApplicationData.Current.LocalSettings.Values["refreshToken"] != null)
    {
        if (await App.SFDC.RefreshToken((string)ApplicationData.Current.LocalSettings.Values["refreshToken"])) LoggedIn();
    }
}

In this function we start by setting the UI to the logged out state and then set the data context to the viewmodel. In the next line we check the users local settings to see if we have saved a refresh token there. If we do have a saved token we use it call RefreshToken and if this is successful we set the logged in state.

Finally we need handlers for the Login and Logout button click events.

private async void UILogin_Click(object sender, RoutedEventArgs e)
{
    if (await App.SFDC.LoginSalesforce())
    {
        if ((bool)UIStayLoggedIn.IsChecked) ApplicationData.Current.LocalSettings.Values["refreshToken"] = App.SFDC.AccessToken.refresh_token;
        LoggedIn();
    }
}

When the login button is clicked we call the LoginSalesforce function which does the OAuth authentication. If the user has checked the stay logged in checkbox we store the refresh token that was returned as part of the access token in the users local settings so we can use it later to re-authenticate without the user having to re-enter their credentials. If the checkbox wasn’t checked we just login for this one session and the user will need to login again next time the application is run. Finally the Logout event handler.

private void UILogout_Click(object sender, RoutedEventArgs e)
{
    ApplicationData.Current.LocalSettings.Values.Remove("refreshToken");
    LoggedOut();
}

When the user logs out we clear the refresh token from the user’s configuration settings and set the form to the logged out state.

You can download the source for this version of the application here.

Saturday, November 24, 2012

Windows 8 + Salesforce.com Part 3

In my last two posts I showed how to connect to Salesforce.com from a Windows 8 Windows Store application, and then how to retrieve a list of accounts. In this article I will show how to display the accounts.
The first thing we need is a view model class to hold the data we want to display. For an application this simple we could get away without a view model but creating one is a good practice and it does make things easier for more complex applications.

public class AccountsViewModel : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<sfdcAccount> accounts;

    public ObservableCollection<sfdcAccount> Accounts
    {
        get { return accounts; }
        set {
            accounts = value;
                if (PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("Accounts"));
        }
    }
  
}

You will notice that that class implements the INotifyPropertyChanged interface. This is needed so that XAML data binding can detect changes to the object. The implementation of the interface is in the first line, the PropertyChanged event which needs to be called whenever a property of the object changes. The rest of the class is a property that holds an ObservableCollection of sfdcAccounts. In the setter you will see that we raise the PropertyChanged event passing in a reference to the object and a PropertyChangedEventArgs object containing the name of the property. Even though this is an ObservableCollection it only allows the data binding to see when items are added to or removed from the collection. The PropertyChanged event is needed to notify data binding if the actual collection object referenced by the property changes.

Next we need a new page to display the accounts, so from the project select Add/New Item, then select Items Page and change the name to AccountsView.xaml. You will get a message asking to add files to your project, select Yes. To have this page displayed at startup open App.xaml.cs and in the OnLaunched function change MainPage in the following line to AccountsView.

if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))

While we are in App.xaml.cs we need to create an sfdcLibrary object that we can use throughout our application. To do this add the following property

public static sfdcLibrary SFDC { get; set; } 

then add the following line to the App() constructor

SFDC = new sfdcLibrary();

Now lets work on the AccountsView we created earlier. In AccountsView.xaml.cs you will notice that the class inherits from LayoutAwarePage. This is a helper class that is part of the Windows Store Application template which wraps the base Page class and provides help with things like navigation.  The first change we need to make in this file is to add this private variable which will hold the view model

private AccountsViewModel model = new AccountsViewModel();

Next replace the LoadState function with this one

protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    this.DataContext = model;
    if (await App.SFDC.LoginSalesforce())
    {
        var acc = await App.SFDC.ReadAccounts();
        model.Accounts = acc.records;
    }
}

LoadState is called in response to the OnNavigatedTo event which happens whenever a page is displayed.  The first thing we do in this function is set the page’s DataContext property to the view model. DataContext will be used as the base for all the data binding we do on the page. Next we call the LoginSalesforce function to do the OAuth login and if it is successful we read the account list from Salesforce and assign it to the Accounts property of the viewmodel.

We are almost done, the final changes we need to make are in AccountsView.xaml. First in the Page.Resources section change the source to point to the Accounts property of the view model like this

Source="{Binding Accounts}"/>

This will bind the Accounts list in our view model to the GridView which will display the data. Next thing we need is a DataTemplate to be used to display each account.

<DataTemplate x:Key="StandardItemTemplate">
    <StackPanel Orientation="Vertical" Width="200" Height="200" Background="#FF07B3F3"  >
        <TextBlock  Text="{Binding Name}" HorizontalAlignment="Center" Margin="20,10,20,0" FontWeight="Bold" TextWrapping="Wrap" FontSize="20" TextAlignment="Center" />
        <TextBlock Text="{Binding AccountNumber}" HorizontalAlignment="Center" Margin="20,10"/>
    </StackPanel>
</DataTemplate>

The template starts with a 200x200 StackPanel with a blue background. Inside this we have two TextBlocks, the first one will show the Name of the account and the second will show the AccountNumber. Finally we need to change the ItemTemplate property of the GridView to use the template we just defined.

ItemTemplate="{StaticResource StandardItemTemplate}"

StaticResource tells XAML that we are using a resource defined elsewhere in the markup, in this case in our Page.Resources section. StandardItemTemplate is the Key property we defined in the template markup.

If we run the application we will first get a Salesforce login screen. Once the correct username and password are entered all the accounts in the Salesforce instance will be displayed.

image

Now that we have a basic working application I will expand on it in future blog posts.
You can download the full source for this application here. To use this code you will need to put your ClientID and ClientSecret in the sfdcLibrary class.

Saturday, November 17, 2012

Windows 8 + Salesforce.com Part 2

This is the second part of a series of posts on how to create a Windows 8 WinRT application that uses the Salesforce REST API. In the first part I showed all the code needed to authenticate to Salesforce. In this post I will show how to to retrieve data from Salesforce. In part 3 we will pull all the pieces together a display the data.
First thing we need is an object model to hold the data we retrieve from Salesforce. For the purposes of this application we will read a list of Accounts. Let’s start with a class to hold a single Account:

public class sfdcAccount
{       
    public sfdcAttributes Attributes { get; set; }

    public string Id { get; set; }
    public string Name { get; set; }
    public string AccountNumber { get; set; }
    public string Type { get; set; }
    public string Phone { get; set; }
    public string WebSite { get; set; }
    public string Industry {get; set;}
    public string BillingStreet { get; set; }
    public string BillingCity { get; set; }
    public string BillingState { get; set; }
    public string BillingPostalCode { get; set; } 
    public string CustomerPriority__c { get; set; }
 }

The first property is of type sfdcAttributes and will be used to hold meta-data about the record, we will look as this class next. The rest of the properties are a selection of fields from the Account record. There are more fields then this in Salesforce but this is a good group to work with. Here is the sfdcAttributes class that holds the type of the record and it’s unique URL. This can be used with any Salesforce object, not just the Account.

public class sfdcAttributes
{
    public string Type { get; set; }
    public string Url { get; set; }
}

Finally, we need a class to hold the meta data that is returned when we query for a group of records.

public class sfdcCollection<T>
{
    public bool done { get; set; }
    public int totalSize { get; set; }
    public string nextRecordsUrl { get; set; }
    public ObservableCollection<T> records { get; set; }
}

I made this a generic class so that it can be used for a collection of any Salesforce object, for example sfdcCollection<sfdcAccount> for a collection of accounts. The records property will hold the collection of sfdcAccounts. In the Windows forms application I made this a List<T> but to facilitate XAML data binding I have made it an ObservableCollection<T> which allows the binding system to detect changes to the collection. You will need to include the System.Collections.ObjectModel namespace to use the ObservableCollection.

In the last post we created a class called sfdcLibrary to hold all our Salesforce related code. We will add the following property and constructor to this class.

public string VersionUrl { get; set; }

public sfdcLibrary()
{
    VersionUrl = "/services/data/v26.0";
}

The Salesforce REST supports multiple versions of the API, so whenever you make a call to the API you must use the URL for the appropriate version. This variable will allow us to specify the version we want to use in one place. In this case we will hard code it to v26.0 of the API.

Now that we have an object model to hold the data we want to display we need some code to read it from Salesforce.


public async Task<sfdcCollection<sfdcAccount>> ReadAccounts()
{
    var query = accessToken.instance_url + VersionUrl + "/query?q=SELECT id,accountNumber,name,BillingStreet,BillingCity,BillingState,BillingPostalCode,CustomerPriority__c,Type,Phone,WebSite,Industry from account";

    var resp = await HttpGet(query);

    sfdcCollection<sfdcAccount> accts = null;

    if (resp.StatusCode == System.Net.HttpStatusCode.OK)
    {
         accts = Deserialize<sfdcCollection<sfdcAccount>>(await resp.Content.ReadAsStringAsync());
    }
    return accts;
}

This function will read all the Account records from your Salesforce instance, and return them in an sfdcCollection of sfdcAccounts (the Task<> is needed  because this is an async function). Reading all the records isn’t really practical in a real world application since it might return a very large number of records, but it is ok for the purposes of this demonstration.

In the first line of the function we build the URI to query for the Account fields we want. The URI starts with the instance URL, we then appends the version URL to this and finally the SOQL query.  The second line uses the HttpGet function to get the results of the query in the form of an HttpResponseMessage object, we will look at HttpGet in a second. Finally we check the HTTP status from the request and if it was successful  we use the Deserialize function which I showed in the last post to turn the JSON response into a object model we can work with.

The final function we need to look at is HttpGet.

public async Task<HttpResponseMessage> HttpGet(string uri)
{
    System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "OAuth " + accessToken.access_token);

    return await client.GetAsync(uri);
}

This works pretty much the same as the HttpPost function I showed in the last blog post.

We now have all the code we need to authenticate to Salesforce and read back a collection of Accounts. In the next post I will show how we display the Accounts.

Tuesday, November 6, 2012

Windows 8 + Salesforce.com Part 1

Over the past year I have written a bunch of articles about interfacing to Salesforce.com and Windows 8 WinRT application, so I thought it was about time to combine the two. This is the first of a series of articles that will show how to write a Windows 8 Win RT application that accesses Salesforce through the REST API.
The first thing you will need to do is setup the REST API in your instance of Salesforce. I covered how to do this in my Salesforce REST API post. Once this setup is done you will get a Consumer Key and Consumer Secret which we will use in a little bit.
To get started with our application,  open up Visual Studio 2012, create a new project and select Visual C#, Windows Store, Blank App (XAML). This will give us a simple base template to build on.
The next step in using the Salesforce REST API is to use OAuth to authenticate to Salesforce. The basic steps for doing this are the same as in the Windows forms app that I described in my original posts, but the details are a little different when implementing the process in a WinRT app. Add a class called sfdcLibrary to the project to hold all the Salesforce access functions, and add the following namespaces:

using System.IO;
using System.Net.Http.Headers;
using System.Runtime.Serialization.Json;
using Windows.Security.Authentication.Web;
using System.Net.Http;

Next add the following private variables to the class

private string clientID = "[Your Consumer Key]";
private string clientSecret = "[Your Consumer Secret]";
private string redirectURL = "resttest:callback";

private TokenResponse accessToken = null;

Be sure to put in the consumer key and consumer secret you got when you setup Remote Access in Salesforce. TokenResponse is a class that will hold all the details that the authentication process sends back. It looks like this.


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; }
}

Now we can look at the code for doing the OAuth login, here is the first part

public async Task<bool> LoginSalesforce()
{
    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);

    var result = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, new Uri(authURI.ToString()), new Uri(redirectURL));

    if (result.ResponseStatus != WebAuthenticationStatus.Success) return false;

First thing you will notice  is the async keyword and the return type of  Task<bool>. These will allow this function to be called asynchronously and are also needed because we will be using async functions. Next we build the URI that is needed to bring up the Salesforce login page to authenticate the user. In the Windows forms application we used a web browser control to handle this, but it turns out to be much easier to do in WinRT by using WebAuthenticationBroker class.


On the WebAuthenticationBroker we call the AuthenticateAsync method. The first parameter just specifies that we don’t want any special options. The second is a URI object  that contains the URI of the page that will do the authentication. When the method is called a new page will be displayed automatically in the application and the web page pointed to by the URI will be displayed so the user can login. The final parameter of the method is used to determine when the login process is complete. It contains the URI that the login page will re-direct to when done, so the AuthenticateAsync function will look for this address to know when to return from the method.

The AuthenticateAsync method will return a  WebAuthenticationResult object that has a ResponseStatus property. This property will have one of three values, Success if the authentication succeeds, UserCancel if the user click the back arrow to cancel the login, or ErrorHttp if there was some sort of HTTP error, for example if the login page could not be found. In this case, if the status is not success we will return false from the function.

If the authentication succeeds we will get something like this back in the WebAuthenticationResult.ResponseData property:

resttest:callback?code=jPrxA6bDXmdSBjzBFDRCwY1D09JvsHbzaL5.ISrdh2PE247HeZH.Qxv4_9p1XwXSMR78xvN8Jw%3D%3D

We need the code so we will use the next two lines to extract it.

string response = result.ResponseData;
string code = response.Substring(response.IndexOf("code=") + 5);

Now we can do the second part of the authentication process

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);
var tokenResponse = await HttpPost(URI, body.ToString());
if (tokenResponse.StatusCode != System.Net.HttpStatusCode.OK) return false;

var data = await tokenResponse.Content.ReadAsStringAsync();
accessToken = Deserialize<TokenResponse>(data);
return true;


The first line contains the URI used to request an access token. Next we build up the body of the request, then call the HttpPost function to get the access token. We will look at this function in a minute. What we get back from the HttpPost function is a HttpResponseMessage object. The HttpPost function doesn’t throw any exceptions if there is an HTTP error so in the next line we need to check the StatusCode property to be sure the request succeeded. If the response succeeded we use the ReadAsStringAsync function to read the data that was returned. Finally we deserialize the JSON data returned from the HttpPost function to create the accessToken object. We will look at the Deserialize function in a minute.

Now lets look at the two helper functions that the login function uses, first HttpPost.

public async Task<HttpResponseMessage> HttpPost(string uri, string body)
{
    var client = new HttpClient();
    var content = new StringContent(body);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
    return await client.PostAsync(uri, content);
}

Just like the login function we are making this one async. It accepts the URI  for the request and the data to be sent in the body of the request and it will return an HttpResponseMessage object. In the Windows forms version we used the WebRequest class but here we will use the HttpClient class which is a little easier to use. First we create an instance of HttpClient. Next we create a StringContent object from the body parameter and then in the next line set the proper ContentType header. Finally we execute the PostAsync method passing in the URI and content then returning the HttpResponseMessage object.

The final function we need to look at is the Deserialize function.

public static T Deserialize<T>(string json)
{
    var bytes = Encoding.Unicode.GetBytes(json);
    using (MemoryStream stream = new MemoryStream(bytes))
    {
        var serializer = new DataContractJsonSerializer(typeof(T));
        return (T)serializer.ReadObject(stream);
    }
}

In the Windows forms app we use the JavaScriptSerializer class to deserialize JSON, but this is not available in WinRT. The alternative is to use the DataContractJsonSerializer. It’s a pretty straight forward function so I am not going to go into the details. Just note that it’s a generic function so T will contain the type that we want to deserialize the Json into.

We now have all the code we need to do OAuth authentication with Salesforce from a WinRT application. In my next post I will show how to retrieve data and then we will get into actually using this code to display the data.

Friday, October 5, 2012

Salesforce REST API Folders and Documents

In a recent post I described how to retrieve a file stored in Salesforce using the REST API. In that post I showed how to retrieve a document using its internal ID number which really isn’t to useful in practice, it would be better to retrieve it by name. In this post I will show how to look at folder and file information in Salesforce. All the queries in this post can be executed using the code I showed in the Salesforce REST API Query post.
Let’s start by looking at folders. You can query for a list of folders by using this SOQL statement:

SELECT ID,Name,DeveloperName FROM folder

This will return a JSON response something like this:

{
  "totalSize" : 1,
  "done" : true,
  "records" : [ {
    "attributes" : {
      "type" : "Folder",
      "url" : "/services/data/v24.0/sobjects/Folder/00lE0000000zg7MIAQ"
    },
    "Id" : "00lE0000000zg7MIAQ",
    "Name" : "Test Folder",
    "DeveloperName" : "Test_Folder"
  } ]
}

In the response you will see a record for each Folder in your Salesforce instance with fields for the ID, the folder name, and the DeveloperName which is a unique name without any spaces.

Now that we have the folder ID we can query for all the documents in that folder.

SELECT ID, Name, DeveloperName FROM document where Folderid='00lE0000000zg7MIAQ'

which will return a response like this:

{
  "totalSize" : 1,
  "done" : true,
  "records" : [ {
    "attributes" : {
      "type" : "Document",
      "url" : "/services/data/v24.0/sobjects/Document/015E00000019TzdIAE"
    },
    "Id" : "015E00000019TzdIAE",
    "Name" : "Test in Folder",
    "DeveloperName" : "Test_in_Folder"
  } ]
}


Just like the folder query this one returns an Id, Name and DeveloperName for each document in the folder. If you want you can also remove the where clause from that query and it will return a list of all documents no matter what folder they are in.

You might think that you could do something like this in one query using a join, but although SOQL does support joins, they don’t work with folders and documents, so you have to do the two separate queries.

Besides Id,Name and DeveloperName there are some other useful fields you can retrieve for a document.

LastModifiedById – Internal ID of the user that last modified the document record.
LastModifiedDate – Date that the document record was last modified.
CreatedById – Internal ID of the user that created the document record.
CreatedByDate – Date the document record was created.
AuthorID – Internal ID of the user who is currently selected as the author of the document.
Type – The file extension of the document.
ContentType – The MIME type of the document.
Keywords – The keywords field in the document record.
Description – The description field in the document record.
IsInternalUseOnly – The boolean Internal Use Only field in the document record.

Saturday, June 30, 2012

Salesforce REST API Read File

In my last post I showed how to upload a file to Salesforce, now lets look at how to read it back. This requires two steps, one to read the document object and a second step to read the actual file data.
Reading the document object is just like reading any other type of object in Salesforce. First we need a class to hold the document object.

public class sfdcDocument
{
    public string Description { get; set; }
    public string Keywords { get; set; }
    public string FolderId { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }
    public string Body { get; set; }
}

Here is the code to retrieve the document object and de-serialize it.

var uri = instanceURL + "/services/data/v24.0/sobjects/Document/015E0000000qhId";

var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + accessToken);
req.ContentType = "application/json";
req.Method = "GET";
  
var resp = req.GetResponse();
var sr = new System.IO.StreamReader(resp.GetResponseStream());
var result = sr.ReadToEnd();

// Convert the JSON response into a token object
JavaScriptSerializer ser = new JavaScriptSerializer();
sfdcDocument doc;
 
doc = ser.Deserialize<sfdcDocument>(result);


First we create the REST URI needed to retrieve the document. We are using the simplest method of reading the document here, by just specifying the id of the document we want to read. There are ways to query by filename but I will cover that at another time. Now we make an HTTP get request, setting the accesstoken to the value we got during the authentication process, then read the response and finally de-serialize it.

The document object contains a field called Body which contains the URI used to retrieve the actual binary file data. Here is the piece of code needed to do that.

System.Net.WebClient client = new System.Net.WebClient();
client.Headers.Add("Authorization: OAuth " + accessToken);
client.DownloadFile(instanceURL + doc.Body, @"c:\temp2\" + doc.Name );


Here we use a WebClient to simplify reading the file. As always we add the access token, then execute DownloadFile using the instanceURL you got along with the access token, and the Body property of the document to specify the whole URI. We can also use the Name property of the document to get the original filename for the document and save it using the same document name.

Sunday, June 3, 2012

Salesforce REST API File Upload

The next part of the Salesforce.com REST API I want to talk about is how to work with documents. In this article I will explain how to upload documents to a folder in Salesforce. Creating a document is similar to creating any other type of Salesforce object so you may want to refer back to my original article on this topic, although I will cover all the code in detail here.
To create a document in Salesforce we will need to post a JSON or XML representation of the document meta-data just like we would with any other Salesforce object, but for a document we will also need to send the binary data from the file. To do this we will send a multi-part MIME document in the body of the HTTP post. The first thing we are going to need is a class to hold the document meta data.

public class sfdcDocument
{
    public string Description { get; set; }
    public string Keywords { get; set; }
    public string FolderId { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }

}

Most of these are self explanatory, but we do need to talk I little about FolderId. When you upload a document to Salesforce you must provide the ID of the folder you want to upload it to. There are ways of querying for folder names, but for the purposes of this demo we will hard code the Id. To get a FolderID log into Salesforce and select the Documents tab. If the tab is not show, click on the + at the end of the tabs and pick Documents from the next screen. From the Folders drop down select the folder you want to upload to and click Go. The next screen will show the contents of you folder and you will be able to get the ID from the URL. For example in “na9.salesforce.com/015?fcf=005E0000000V7Ep” the folder ID is 005E0000000V7Ep.

Now lets look at the code to upload a document.

var doc = new sfdcDocument();
doc.Name = "TestDocument";
doc.FolderId = "005E0000000V7Ep";

First we create a new sfdcDocument object and populate the required fields. You will need to replace the FolderID with the one for the folder you will use.
string boundary = "----" + DateTime.Now.Ticks.ToString("x");
This line is used to create a boundary string to separate the parts of the multi-part MIME message we are going to build. This can be any value that we are sure will not appear somewhere else in the message.
var uri = instanceURL + "/services/data/v24.0/sobjects/Document/";
var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + accessToken);
req.ContentType = "multipart/form-data; boundary=" + boundary;
req.Method = "POST";
var os = req.GetRequestStream();

Now we can build the HttpWebRequest object. In the first line we create the URI for the document resource. The instanceURL variable is the url of your specific Salesforce instance. You will get this when you request an access token during the authentication process. Next we create the request object and set the Authorization header. The variable accessToken in the token you received during the authentication process.  The next line sets the content type for the message. For normal Salesforce object this would be json or xml, but in this case we specify a multpart type and pass the boundary string we created earlier. Finally we set the http method to POST and create a variable for the request stream.

// Add header for JSON part
string body = "";
body += "\r\n--" + boundary + "\r\n"; ;
body += "Content-Disposition: form-data; name='entity_document'\r\n";
body += "Content-Type: application/json\r\n\r\n";

// Add document object data in JSON
var ser = new JavaScriptSerializer();
body += ser.Serialize(doc);

The next step is to add the JSON encoded meta data for the document. We start building the message body by included in the boundary string to mark the start of the first message part. The next two lines are the header for this part of the request. Since we are sending the meta data in JSON format we set the content type to “application/json”. Finally we serialize our document object and added it to the request body.

// Add header for binary part 

body += "\r\n--" + boundary + "\r\n"; ; body += "Content-Disposition: form-data; name='Body'; filename='test.pdf'\r\n"; body += "Content-Type: binary/octet-stream\r\n\r\n";
Now we are ready to setup the binary part of the message. It starts with a header that is similar to the one on the JSON part. In the second line we specify the filename of the document. This filename doesn’t appear to be used anywhere since the actual document in Salesforce uses the Document Name for it’s filename, but the filename attribute must be present and it must contain a value. The third line specifies the content (MIME) type of the file. It is important that this is set correctly so that the file will open in the right program when you open it from Salesforce. An easy way to determine the correct content type is to manually load a file into Salesforce and check the MIME type that it assigns.


// Add header data to request
byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
os.Write(data, 0, data.Length);

// Add file to reqeust
FileStream fileStream = new FileStream(@"c:\temp\test.pdf", FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
    os.Write(buffer, 0, bytesRead);
}
fileStream.Close();

Now we need to add everything to the request stream. The first part of this code writes all the header information to the request stream, and the second part writes the actual binary contents of the file to the stream.

// Add trailer
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
os.Write(trailer, 0, trailer.Length);
os.Close();

To complete the request we add a trailer string to it, and then close the stream.

// Do the post and get the response.
WebResponse resp;

try
{
    resp = req.GetResponse();
}
catch (WebException ex)
{
    resp = ex.Response;
}

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

Finally we send the request and get the response. If an error occurs with the request an exception will be thrown. Here we catch that exception and get the actual response from the Exception.Response property. This will normally contain some useful error messages generated by Salesforce. If we have done everything right we should get a response like this:

{
    "id":"015E0000000qhJeIAI",
    "errors":[],
    "success":true
}

The success property will tell you if the insert succeeded and the id property will contain the a unique id for the document that was created.

One important thing to note about doing a document insert is that it will always create a new document even if you insert a document with the same name as one already in the folder. Salesforce will create a unique name for each document you insert.

Saturday, May 12, 2012

Salesforce Password Login

I recently got an e-mail with a question on the Salesforce REST API that I thought I had covered, but it looks like I didn’t. The question is, is there a way to use the REST API with a username and password instead of OAuth? The answer is yes, and this article will explain how to do it.

You will want to refer to my original article on the Salesforce.com REST API since there are a number of concepts that are the same which I will not cover in detail here.

The first thing you will need to do is setup Remote Access in Salesforce.com just like you do when you access the REST interface using OAuth. Refer to my original article for instructions on how to do this. Once setup you will get a Consumer Key and Consumer Secret which you will need for the password login process.

You will also need, of course, a Salesforce username and password you want to login in with. Finally you will need the Security Token for that account. To get this, login to Salesforce with that account, click the down arrow next to your name in the top right and click Setup, click the down arrow next to My Personal Information on the left, click Reset My Security Token, then click the Reset Security Token button. Once you do this a new security token will be sent to the e-mail address you have configured for this account. 

You can get around using the security token by registering an IP address or range of IP addresses as trusted. To do this, in the Salesforce setup, select Network Access from the Security Controls section. On that screen you can enter one or more ranges of IP addresses of computers you trust. You would have to register the IP address of any computer that is going to make calls to the REST API.

Now that we have this information we can make a call to Salesforce to get the access token that will be needed to make all the other REST calls. Here is the code to do this.

private void GetToken(string consumerKey, string consumerSecret,string username, string password, string securityToken) { 
            string URI = "https://login.salesforce.com/services/oauth2/token"; 
            StringBuilder body = new StringBuilder(); 
            body.Append("grant_type=password&"); 
            body.Append("client_id=" + consumerKey + "&"); 
            body.Append("client_secret=" + consumerSecret + "&"); 
            body.Append("username=" + username + "&"); 
            body.Append("password=" + password + securityToken); 
            string result = HttpPost(URI, body.ToString()); 
        }


This is similar to the code we used get the access token using OAuth but instead of passing in the authentication code we use the username password and security token instead. You will notice that the security token is simply appended to the end of the password. If you have registered your computer as trusted you will just be sending the password without the security token.

This function will return a string containing the access token structure encoded in JSON. Refer to the original article for details on how to extract the access token. Once you have the access token the REST API can be used just like you do when logging in with OAuth.

I have attached a new demo application that shows how to access the REST API using both OAuth and username/password authentication. Be sure to fill out the variables at the top of MainForm.cs with your consumer Key, consumer Secret, etc.
Visual Studio 2010 Salesforce REST API Demo

Sunday, February 27, 2011

Salesforce REST API Query Deserialization


In my last article about the Salesforce REST API I showed how to query for records. The JSON encoded result of the query looks something like this:

{
"totalSize" : 2,
"done" : true,
"records" : [ {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000Q9SFkAAN"
},
"Id" : "0017000000Q9SFkAAN",
"AccountNumber" : "12345",
"Name" : "Big Account"
}, {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000O1LiGAAV"
},
"Id" : "0017000000O1LiGAAV",
"AccountNumber" : "6789",
"Name" : "Small Account"
}]
}


The next question is how to de-serialize this back into an object. Like I have shown before we can use the JavaScriptSerializer class in the .NET Framework to do this, but what would the object model have to look like? One way we could do it is like this:

public class sfdcAttributes
{
    public string Type { get; set; }
    public string Url { get; set; }
}


public class sfdcAccount
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string AccountNumber { get; set; }

    public sfdcAttributes Attributes { get; set; }    
}

public class sfdcAccountCollection
{
    public bool Done { get; set; }
    public int TotalSize { get; set; }
    public string nextRecordsUrl { get; set; }
    public List<sfdcAccount> Records { get; set; }
}


This will work but it has two problems. First we would have to create a collection class for each SFDC object we want to work with and most of the code for that class would be duplicated from one object to the next. The second problem is that because we put the Attributes property in the sfdcAccount class we can’t use it do do inserts or updates since Attributes isn’t a property on the Account object.


To solve the first problem we can use generics:

public class sfdcCollection<T>
{
    public bool Done { get; set; }
    public int TotalSize { get; set; }
    public string nextRecordsUrl { get; set; }
    public List<T> Records { get; set; }
}


This is a generic SFDC collection class that we can use with any type of object. To solve the second problem we need to pull out the Attributes property. Here is a way to handle that:

public class sfdcAccountForCollection : sfdcAccount
{
    public sfdcAttributes Attributes { get; set; }

}


Here we create a class just for use with the collections that are returned by the query function. We inherit from the base sfdcAccount class so it keeps this additional class very simple. To use these classes to de-serialize the JSON response, we just do this:

sfdcCollection<sfdcAccountForCollection> accts = ser.Deserialize<sfdcCollection<sfdcAccountForCollection>>(json);

Wednesday, February 9, 2011

Salesforce REST API Query

A couple weeks ago we looked at how to read a record from SFDC using the REST API. The read function has limited usefulness since it requires us to know the internal ID of a record to be able to read it, and in most cases you won’t know this ID. A more useful way of reading records is to use the Query function.
Query allows you to execute Salesforce Object Query Language (SOQL) queries to retrieve a set of records.  SOQL is similar to an SQL SELECT statement. I am not going to go into the details of SOQL, but you can learn more about it here.
The code for doing a Query is pretty much the same as the code I presented in the Salesforce REST API Read Record article, the only difference being the URI. The URI will look something like this:

var uri = instanceURL + “/services/data/v20.0/query?q=SELECT id,accountNumber,name from account


You will see that we have added a query string called q that contains the SOQL query. Note that in SOQL you must specify all the fields you want returned. There is no equivalent of ‘SELECT *’ in SOQL.


The response from the query will look something like this:


{
"totalSize" : 2,
"done" : true,
"records" : [ {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000Q9SFkAAN"
},
"Id" : "0017000000Q9SFkAAN",
"AccountNumber" : null,
"Name" : "Big Account"
}, {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v20.0/sobjects/Account/0017000000O1LiGAAV"
},
"Id" : "0017000000O1LiGAAV",
"AccountNumber" : "CC978213",
"Name" : "GenePoint"
}]
}


The first things in the response are two fields called totalSize and done. These are important because there is a limit to the number of record a query can return. My experimentation showed the limit to be 2000 records in this case, but that limit my be different in other situations. The totalSize property tells you how many records met the criteria of the query, even if that total is greater then the record limit. If the total is greater then the done property will be false and there will be an additional property called nextRecordsUrl that looks like this:


"nextRecordsUrl" : "/services/data/v20.0/query/01g7000000FBzMHAA1-2000"


To get the next batch of records you would do another HTTP GET using this URL, and then repeat the process until the done property comes back true.


The actual results of the query will be contained in the records array. Each record will contain a series of attributes, one of which is the URL you can use to read the entire record. Following the attributes will be the fields that you requested in the query.

Saturday, January 29, 2011

Salesforce REST API Update and Delete Record

So far we have looked at how to create and read records from Salesforce using the REST API, so the final two basic operations we need are Update and Delete.

Update

The code for doing an update is almost identical to the code for doing an insert with just two small differences.
First we need to specify the ID of the record we want to update in the URI just like we did for a read:

var uri = instanceURL + "/services/data/v20.0/sobjects/Account/0017000000hX4Iz";

Second we will use PATCH for the HTTP method instead of POST. Not that PATCH isn’t a standard HTTP method, but fortunately the .NET WebRequest class allows for arbitrary methods.
Just like with an insert you put the JSON or XML encoded object into the body of the request. You can put all the fields in the body or just the ones you want to update.  If you decide to use XML for the body don’t forget to change the ContentType from JSON to XML:

req.ContentType = "application/xml";

The only other difference with an update is the response. Unlike the other function we have looked at so far, the content of the response will be empty if the update succeeds.


Delete

Delete is probably the simplest operation. We use the same URI as an update, one that contains the id of the record we want to delete, and set the HTTP method to DELETE. Nothing needs to be put in the body of the request for a delete. Just like an update, if the delete is successful the response will be empty.

Sunday, January 16, 2011

Salesforce REST API Read Record

In my last post I showed how to create a new record in Salesforce using the REST API, now lets look at reading a record.
To access a record you need to add the record’s id to the end of the object URI that I showed in the last post. For example to access a specific account record you would use:
http://na1.salesforce.com/services/data/v20.0/sobjects/Account/001D000000INjVe
The id’s aren’t shown directly when you edit a record in SFDC, but you can find the record id in the URL when you are editing a record. You can also get an id from the response when you create a record as we saw last time.
The code to perform the read will look something like this:

public string ReadData()
{
var uri = instanceURL + "/services/data/v20.0/sobjects/Account/0017000000hX4Iz";

var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + accessToken);
req.Headers.Add("X-PrettyPrint:1");
req.ContentType = "application/json";
req.Method = "GET";

WebResponse resp;

try
{
resp = req.GetResponse();
}
catch (WebException ex)
{
resp = ex.Response;
}

var sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}

This is pretty much the same code we used for the insert but it uses an HTTP GET instead of POST,  and there is no body needed for the request. You will also notice a new header, X-PrettyPrint:1. This will make SFDC return the response in a more readable format with appropriate line breaks and indentation. This header can be used in any of the REST API commands.

The response will contain the JSON formatted Account object. Remember, as always, you can add .xml to the end the URI to have the response returned in XML instead of JSON.

By default this command will return all the fields in the record. You can specify only the fields you want to return like this:

http://na1.salesforce.com/services/data/v20.0/sobjects/Account/001D000000INjVe?fields=AccountNumber,Name

We have added a query string called fields to the URI which lists the fields you want to return.

Saturday, January 8, 2011

Salesforce REST API Record Creation

In my last few articles I showed the basics of how to connect to Salesforce using the REST API and how to use some basic functions. Now lets look at how to actually manipulate the data stored in SFDC. We will start by looking at how to insert a new record.
When you are working with tables (called objects in the SFDC nomenclature), the URI will look something like this:
http://na1.salesforce.com/services/data/v20.0/sobjects/Account/

  • http://na1.salesforce.com  is the instance URL that you get during the login process.
  • /services/data/v20.0/ indicates the version of SFDC you will be using.
  • sobjects/ is the resource we will be accessing, in this case the SFDC objects (tables).
  • Account/ is the name of the object we will be creating the new record in.
To insert a new record we will do an HTTP POST to this URI. In the headers we will pass the authorization token, and in the body we will pass the JSON encoded data we want to insert. For example here is a simple piece of JSON that will insert a new Account with the name TestAccount and number 1234567.
{    
"Name" : "TestAccount",
"AccountNumber" : "1234567"
}

Now lets look at the C# code to perform this insert. First, to simplify the creation of our JSON lets create an Account class that we can serialize.

public class sfdcAccount
{
public string Name { get; set; }
public string AccountNumber { get; set; }

}

Next we will setup our URI and the account object

var uri = instanceURL + "/services/data/v20.0/sobjects/Account/";

var acct = new sfdcAccount();
acct.Name = "NewAccount";
acct.AccountNumber = "123456";

and then serialize the account object into JSON.

var ser = new JavaScriptSerializer();
var body = ser.Serialize(acct);

We can now create our HTTP request.

var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + accessToken);
req.ContentType = "application/json";
req.Method = "POST";


Here we create an HttpWebRequest object pointing to the URI we specified earlier. We then set a header that contains the access token we got during the login process, set the content type to JSON and finally specify that this is an HTTP POST request.

Next we need to add the body of the request. This code will convert our JSON to a byte array an attach it to the request.

byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
req.ContentLength = body.Length;
var os = req.GetRequestStream();
os.Write(data, 0, data.Length);
os.Close();

Finally we execute the request and retrieve the result that SFDC sends back.

WebResponse resp;

try
{
resp = req.GetResponse();
}
catch (WebException ex)
{
resp = ex.Response;
}

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

The try/catch around the request is important. When there is an error executing the command SFDC will return a HTTP response code of 400 which will throw an exception. To resolve this problem we catch the exception and retrieve the response object from the exception.

Assuming there are no errors, SFDC will return a JSON response that looks like this

{
"id":"0017000000hX4BIAA0",
"errors":[],
"success":true
}

First we get back the internal id of the record that was created. We can use this later to read, update, or delete this record. We also get back a true/false field indicating the success or failure of the insert and an errors field. I have not yet found a case where these are used since an error will return a different response. For example if we make the AccountNumber greater the 40 characters we will get the following response:

{
"fields":["AccountNumber"],
"message":"Account Number: data value too large: 1234567890123456789012345678901234567890123456789012345678901 (max length=40)",
"errorCode":"STRING_TOO_LONG"
}

Friday, November 5, 2010

Salesforce REST API Access Token

In my first article on the SFDC REST API I showed how you authenticate to Salesforce using OAuth. The main output of this process is the access token which must be provided when you make any other calls to the REST API. One of the first things I wondered about the access token is, how long does it last? It turns out that the access token is tied to the normal session timeout in SFDC and is configurable for each instance. To view or change the setting log into your account, click Setup, then under Administration Setup select Security Controls then Session Settings.
image
You can see that in this case the timeout is set to two hours. This means that if you go for more the two hours without calling the REST API the access token will expire. You can change this setting from between 15 minutes and 8 hours.
The next question is, when the access token expires does the user have to go through the login process again? Fortunately the answer is no, this is where the refresh token comes into play. When we did the initial authentication process to get the access token we also received a refresh token. The refresh token can be used to get a new access token without the user having to enter their username and password again.
The code to get a new access token is pretty much the same as the code we initially used to get access token.

{ 

string URI = "https://login.salesforce.com/services/oauth2/token";
StringBuilder body = new StringBuilder();


body.Append("refresh_token=" + refreshToken + "&");
body.Append("grant_type=refresh_token&");
body.Append("client_id=" + clientID + "&");
body.Append("client_secret=" + clientSecret + "&");
body.Append("redirect_uri=" + redirectURL); 

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

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

} 

You will notice two differences. First instead of passing the code we got when the user logged in, we pass the refresh token, and second we set the grant type to refreshToken instead of authorization_code. The function will return the same response as the initial call did with one exception. According to the OAuth specs the service is not required to return a new refresh token when a new access token is generated. This appears to be the case with SFDC since this call does not return a new refresh token. This means that you need to hold onto the original refresh token to use each time you request a new access token.

Monday, November 1, 2010

Salesforce REST API Part 2

In my last post I introduced the new Salesforce REST API. Now I will dig into some of the details of how to use the interface.

URIs

Like any REST API you access resources in Salesforce using various URIs like this:
http://na1.salesforce.com/services/data/v20.0/sobjects/Account/
The first part of the URI "http://na1.salesforce.com/" identifies your Salesforce instance. This is needed because different accounts will be hosted on different servers. As I showed in the last article you retrieve the instance URL during the authentication process.
The next piece "/services/data" identifies the service and is the same for all REST API calls. The following piece "v20.0/" is the version number which specifies the version of the API you want to use. You can retrieve a list of the available versions by calling the List Versions command which I will show in a minute. The Version command will return a URL that contains both the service and version parts of the URI.
Next 'sobjects' is the resource you will be calling. You can get a list of the available resources using the List Resources command.
Finally anything after the resource is specific to the resource and command you are calling.

Return Type

By default the REST API returns its results in JSON format. You can also request that the results be returned in XML. To do this just append .xml to the end of the URI you are calling. The documentation also indicates that you can do this using the HTTP ACCEPT header, but I have not been able to get that to work. I my examples I will be showing the results in XML.

List Versions Command

The list versions command looks like this:
https://na5.salesforce.com/services/data/.xml
Note that in all my examples I will be using the instance URL of my account, be sure to substitute your own.
Here is what is returned:
<?xml version="1.0" encoding="UTF-8"?>
<Versions>
<Version>
<label>Winter &apos;11</label>
<url>/services/data/v20.0</url>
<version>20.0</version>
</Version>
</Versions>


In this case there is only one version available, version 2.0. Also returned is the label for the version "Winter '11" and the URL to access the API for this version. One thing to note about this command is that you do not need to authenticate before calling it. It works whether you pass the access token or not.


List Resources Command

The next command you will want to know about lists the resources available for a specific version. The command looks like this:

http://na1.salesforce.com/services/data/v20.0/.xml

Remember if you want to return the results in JSON format just leave off the .xml or specify .json instead of .xml.

The result looks like this:


<?xml version="1.0" encoding="UTF-8"?>
<urls>
<sobjects>/services/data/v20.0/sobjects</sobjects>
<search>/services/data/v20.0/search</search>
<query>/services/data/v20.0/query</query>
<recent>/services/data/v20.0/recent</recent>
</urls>


This shows the resources that are accessible through the API. The current resources are:

sobjects – Allows you to access information about the objects in the database and to insert, read, updated and delete objects.

query – Allows you to run SOQL queries.

search – Allows you to run a SOSL search.

recent – This seems to return a list of recent objects, but I haven't found any official documentation on it.

That's all for now. In future postings I will get into some more details on how each of these resources is used.

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