2
votes

I'm new to Salesforce development, and trying to figure out SOQL stuff. Long time listener, first time caller.

I am running a SOQL query on ActivityHistories, and attempting to get it as a custom object. I need to do this so I can bind the data to an ASP.Net datagrid. Unfortunately, the dynamic type won't work for me, because I can't bind that to the grid.

Here is my query:

var activities = await client.QueryAsync<Activity>(@"SELECT (SELECT ActivityDate, Description 
FROM ActivityHistories
ORDER BY ActivityDate DESC NULLS LAST, LastModifiedDate DESC LIMIT 500)
FROM Account
WHERE Id = '" + SalesforceId + "' LIMIT 1");

And here's the custom data type I want to use

public class Activity
    {
        public DateTime ActivityDate { get; set; }
        public string Description { get; set; }
    }

When I run this request and bind the activities.records to the datagrid, I simply get no data. The headers for the columns appear, but I don't get any of the records that are supposed to be there. Even debugging doesn't provide any additional information, it just looks like I got a blank object back. However, when I run the same query and replace Activity with dynamic, I get a whole bunch of Json that does contain everything I'm looking for.

At first, I thought maybe the deserialization into my custom object was the problem, but I did a very similar thing with Opportunity, and it works just fine, automatically converting to that custom object. This leads me to believe I'm handling something with the inner query incorrectly, and I would greatly appreciate any direction.

Here's a short summary of stuff I have read and attempted:

Thank you in advance!

2

2 Answers

2
votes

Under the hood, the Salesforce API is a collection of JSON services. The DeveloperForce toolkit (which you appear to be using) is not seeing a structure in your result object that matches the JSON object returned. This is because the nested query returns an object which has multiple levels of nested objects. Something like this:

  • Result of Query
    • Account
      • Result of Activity History Query
        • List of Activity History Records

The serialization library has taken care of the first and second levels for you. You now have to provide an object to de-serialize into which can accommodate the third and fourth levels.

I did some testing with similar code and found a hierarchy like this should work:

public class ActivityQueryContainer
{
    public Dictionary<string, string> Attributes { get; set; }
    public ActivityHistoryResult ActivityHistories { get; set; }
}

public class ActivityHistoryResult
{
    public Activity[] Records { get; set; }
}

public class Activity
{
    public DateTime ActivityDate { get; set; }
    public string Description { get; set; }
}

You can then change your API call to look like this:

var activities = await client.QueryAsync<ActivityQueryContainer>(@"SELECT (SELECT 
    ActivityDate, Description FROM ActivityHistories ORDER BY ActivityDate DESC NULLS LAST, 
    LastModifiedDate DESC LIMIT 500) FROM Account WHERE Id = '" + SalesforceId + "' LIMIT 1");
1
votes

You can always cast the result to a type "object" which will return the JSON string, use a tool such as http://json2csharp.com/ to create the model for you.