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

Thursday, February 24, 2011

log4net Presentation

 

For anyone who attended my presentation on log4net at the PhillyNJ.NET meeting 2/21/2011, here are the related file.

Power Point Presentation

log4net Demo Source Code

If you are in South Jersey of the Philadelphia area be sure to check out the next meting on March 29th where David Isbitski from Microsoft will do a presentation on Real World Windows Phone 7 Development.

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.