Skip to content

About

Salesforce REST API toolkit for .NET Standard and .NET Core

Topics

Resources

Stars

127 stars

Watchers

9 watching

Forks

Repository files navigation

NetCoreForce

A Salesforce REST API client library for .NET and C#

This project is not offered, sponsored, or endorsed by Salesforce.

NetCoreForce lets .NET applications query, create, update and delete Salesforce records through the Salesforce REST API, with OAuth 2.0 login, SOQL and SOSL queries, composite requests, and strongly typed models for Salesforce objects.

NuGet Version NuGet Downloads

Documentation

Install

dotnet add package NetCoreForce.Client
dotnet add package NetCoreForce.Models

Quick Start

// Log in with the OAuth Client Credentials flow
ForceClient client = await ForceClient.FromClientCredentialsAsync(
    "your-client-id", "your-client-secret", "https://your-domain.my.salesforce.com/services/oauth2/token");

// Query records
List<SfAccount> accounts = await client.Query<SfAccount>("SELECT Id, Name FROM Account LIMIT 10");

See the Authentication and Examples docs for other login flows and more usage examples.

Changes in v6

  • Breaking: removed .NET Core 3.1 and .NET 5.0 - 7.0 targets. These may still work via .NET Standard 2.0, but are no longer tested. The ModelGenerator tool now requires .NET 8.0+.
  • Breaking: record IDs and object/field names are validated to prevent URL path injection. Invalid values throw an ArgumentException.
  • Added .NET 10.0 and .NET Framework 4.8.1 targets
  • Added Client Credentials login flow, via ForceClient.FromClientCredentialsAsync and in the ModelGenerator
  • Added SoqlHelpers for escaping untrusted values in SOQL and SOSL queries
  • External ID values are now URL-encoded in upserts
  • Default Salesforce API version is now v67.0
  • Fixed TokenRefreshAsync discarding the new refresh token when refresh token rotation is enabled
  • Fixed timezone offset formatting under .NET Framework 4.x

Library Targets

The primary target is .NET Standard 2.0 to provide the widest possible support.

  • .NET Standard 2.0 for widest possible support including .NET Framework 4.6.2+
  • .NET Standard 2.1 for newer .NET Core versions

For more info on .NET Standard compatibility see the Microsoft documentation here

Full target list

  • .NET Standard 2.0
  • .NET Standard 2.1
  • .NET 8.0
  • .NET 9.0
  • .NET 10.0
  • .NET Framework 4.6.2
  • .NET Framework 4.7.2
  • .NET Framework 4.8 & 4.8.1

All possible frameworks are specifically targeted so that conditional compilation can be done where required.

Full tested support is for .NET Core 8.0 - 10.0 as tooling and tests target those.

CI main:
CI
CI dev:
CI

Projects in this solution:

NuGet Packages

Designed to minimize dependencies:

(Migration from Newtonsoft.Json to System.Text.Json is planned)

Feedback and suggestions welcome.

Licensed under the MIT license.

Basic Usage Example

///Initialize the authentication client
AuthenticationClient auth = new AuthenticationClient();

//Pass in the login information
await auth.UsernamePasswordAsync("your-client-id", "your-client-secret", "your-username", "your-password", "token-endpoint-url");

//the AuthenticationClient object will then contain the instance URL and access token to be used in each of the API calls
ForceClient client = new ForceClient(auth.AccessInfo.InstanceUrl, auth.ApiVersion, auth.AccessInfo.AccessToken);

//Retrieve an object by Id
SfAccount acct = await client.GetObjectById<SfAccount>(SfAccount.SObjectTypeName, "001i000002C8QTI");
//Modify the record and update
acct.Description = "Updated Description";
await client.UpdateRecord<SfAccount>(SfAccount.SObjectTypeName, acct.Id, acct);
//Delete the record
await client.DeleteRecord(SfAccount.SObjectTypeName, acct.Id);

//Get the results of a SOQL query
List<SfCase> cases = await client.Query<SfCase>("SELECT Id,CaseNumber,Account.Name,Contact.Name FROM Case");

Nested Query Results

When you include related objects in a SOQL query:

SELECT Id,CaseNumber,Account.Name,Contact.Name FROM Case

And get the results via the client, you can then access the related objects and fields included in the query in a fluent manner.

List<SfCase> cases = await client.Query<SfCase>("SELECT Id,CaseNumber,Account.Name,Contact.Name FROM Case");
SfCase firstCase = cases[0];
string caseNumber = firstCase.CaseNumber;
string caseAccountName = firstCase.Account.Name;
string caseContactName = firstCase.Contact.Name;

Nested queries are not fully supported - the subquery results will not be complete if they exceed the batch size as the NextRecordsUrl in the subquery results is not being acted upon. Instead use the relationship syntax in the example above.

// *NOT* fully supported
"SELECT Id,CaseNumber, (Select Contact.Name from Account) FROM Case"

Asynchronous Batch Processing

Query method will retrieve the full result set before returning. By default, results are returned in batches of 2000. In cases where you are working with large result sets, you may want to use QueryAsync to retrieve the batches asynchronously for better performance.

// First create the async enumerable. At this point, no query has been executed.
// batchSize can be omitted to use the default (usually 2000), or given a custom value between 200 and 2000.
IAsyncEnumerable<SfContact> contactsEnumerable = client.QueryAsync<SfContact>("SELECT Id, Name FROM Contact ", batchSize: 200);

// Get the enumerator, in a using block for proper disposal
await using (IAsyncEnumerator<SfContact> contactsEnumerator = contactsEnumerable.GetAsyncEnumerator())
{
    // MoveNext() will execute the query and get the first batch of results.
    // Once the inital result batch has been exhausted, the remaining batches, if any, will be retrieved.
    while (await contactsEnumerator.MoveNextAsync())
    {
        SfContact contact = contactsEnumerator.Current;
        // process your results
    }
}

About

Salesforce REST API toolkit for .NET Standard and .NET Core

Topics

Resources

Stars

127 stars

Watchers

9 watching

Forks

Releases

Packages

Used by

Contributors

Languages