0
votes

NB: This is a duplicate of my question on https://github.com/developerforce/Force.com-Toolkit-for-NET/issues/357. I'll sync both threads after this is resolved.

I'm using the Force.com toolkit for .NET. SOQL queries are working fine for me, but I'm trying to also make a simple REST call similar to one I can make with the REST Explorer tool at https://workbench.developerforce.com/restExplorer.php.

My code is:

 using (var queryClient = new ForceClient(authClient.InstanceUrl, authClient.AccessToken, authClient.ApiVersion))
    {
        // Works fine
        string soql = GetMyQuery();
        QueryResult<dynamic> result = await queryClient.QueryAsync<dynamic>(soql);

        // Throws exception.  Changing version # doesn't seem to have any effect.
        dynamic restResult = await queryClient.ExecuteRestApiAsync<dynamic>("/services/data/v46.0/sobjects/Task/describe");

When I get to ExecuteRestApiAsync, I get the exception:

Salesforce.Common.ForceException
 HResult=0x80131500
 Message=Could not find a match for URL
 Source=Salesforce.Common
 StackTrace:
  at Salesforce.Common.JsonHttpClient.<HttpGetAsync>d__4`1.MoveNext()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
[...]

I assume that my argument "/services/data/v46.0/sobjects/Task/describe", which works fine in the REST Explorer tool, needs to change. But I've guessed a bunch of different options (different versions, with or without leading URL string, etc.) and so far haven't gotten anything to work.

Can someone tell me how to use ForceClient to get the same results I get back from the Salesforce Workbench REST Explorer?

1
The connection is using http request/response. So easiest method is to use a sniffer like wireshark or fiddler and compare the first request in the working force.com toolkit with the non working c# application. Make the c# request look exactly like the working force.com toolkit.jdweng

1 Answers

0
votes

I ended up looking more closely at the ForceClient code. ExecuteRestApiAsync was not the correct call for this. For my specific example, there are 3 ways I found that work:

dynamic restResult = await queryClient.DescribeAsync<dynamic>("Task");
restResult = await queryClient.BasicInformationAsync<dynamic>("Task/describe/");
restResult = await queryClient.BasicInformationAsync<dynamic>("Task/describe");

(All 3 of the above lines return the same result)

This will work fine for sobjects. I don't think it's currently possible to use this library directly for things like reports which use "analytics" in their REST API definitions, but there are a couple workarounds that don't require recompiling the code. The cleanest and most performant of these that I've found is to pass your own HttpClient instances into the ForceClient ctor and use those directly instead of the methods on the ForceClient. An inspection of the ForceClient code will reveal that most of these methods are just thin string.Format() wrappers on HttpClient methods anyway.