/// <summary> /// Updates /// </summary> /// <param name="sObjectTypeName">SObject name, e.g. "Account"</param> /// <param name="objectId">Id of Object to update</param> /// <param name="sObject">Object to update</param> /// <param name="customHeaders">Custom headers to include in request (Optional). await The HeaderFormatter helper class can be used to generate the custom header as needed.</param> /// <returns>void, API returns 204/NoContent</returns> /// <exception cref="ForceApiException">Thrown when update fails</exception> public async Task UpdateRecord <T>(string sObjectTypeName, string objectId, T sObject, Dictionary <string, string> customHeaders = null) { Dictionary <string, string> headers = new Dictionary <string, string>(); //Add call options Dictionary <string, string> callOptions = HeaderFormatter.SforceCallOptions(_clientName); headers.AddRange(callOptions); //Add custom headers if specified if (customHeaders != null) { headers.AddRange(customHeaders); } var uri = UriFormatter.SObjectRows(_instanceUrl, _apiVersion, sObjectTypeName, objectId); using (var httpClient = new HttpClient()) { JsonClient client = new JsonClient(_accessToken, httpClient); await client.HttpPatchAsync <object>(sObject, uri, headers); return; } }
public void CallOptionsHeaderWithDefaultNamespaceParameter() { Dictionary <string, string> customHeaders = HeaderFormatter.SforceCallOptions(defaultNamespace: "Test"); Assert.Single(customHeaders); var header = customHeaders.First(); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("Sforce-Call-Options: client=ForceClient, defaultNamespace=Test", result); }
/// <summary> /// Get SObject by ID /// </summary> /// <param name="sObjectTypeName">SObject name, e.g. "Account"</param> /// <param name="objectId">SObject ID</param> /// <param name="fields">(optional) List of fields to retrieve, if not supplied, all fields are retrieved.</param> public async Task <T> GetObjectById <T>(string sObjectTypeName, string objectId, List <string> fields = null) { Dictionary <string, string> headers = HeaderFormatter.SforceCallOptions(_clientName); var uri = UriFormatter.SObjectRows(_instanceUrl, _apiVersion, sObjectTypeName, objectId, fields); using (var httpClient = new HttpClient()) { JsonClient client = new JsonClient(_accessToken, httpClient); return(await client.HttpGetAsync <T>(uri, headers)); } }
public void CallOptionsHeaderWithClientParameter() { Dictionary <string, string> customHeaders = HeaderFormatter.SforceCallOptions("Test"); Assert.Equal(1, customHeaders.Count); var header = customHeaders.First(); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("Sforce-Call-Options: client=Test", result); }
/// <summary> /// Delete record /// </summary> /// <param name="sObjectTypeName">SObject name, e.g. "Account"</param> /// <param name="objectId">Id of Object to update</param> /// <returns>void, API returns 204/NoContent</returns> /// <exception cref="ForceApiException">Thrown when update fails</exception> public async Task DeleteRecord(string sObjectTypeName, string objectId) { Dictionary <string, string> headers = HeaderFormatter.SforceCallOptions(_clientName); var uri = UriFormatter.SObjectRows(_instanceUrl, _apiVersion, sObjectTypeName, objectId); using (var httpClient = new HttpClient()) { JsonClient client = new JsonClient(_accessToken, httpClient); await client.HttpDeleteAsync <object>(uri, headers); return; } }
/// <summary> /// Retrieve (basic) metadata for an object. /// <para>Use the SObject Basic Information resource to retrieve metadata for an object.</para> /// </summary> /// <param name="objectTypeName">SObject name, e.g. Account</param> /// <returns>Returns SObjectMetadataBasic with basic object metadata and a list of recently created items.</returns> public async Task <SObjectBasicInfo> GetObjectBasicInfo(string objectTypeName) { try { Dictionary <string, string> headers = HeaderFormatter.SforceCallOptions(_clientName); //need to get the token from user_authentication using (var httpClient = new HttpClient()) { var client = new JsonClient(_accessToken, httpClient); return(await client.HttpGetAsync <SObjectBasicInfo>(_uri, headers)); } } catch (Exception ex) { return(null); } }
/// <summary> /// Get a basic SOQL COUNT() query result /// <para>The query must start with SELECT COUNT() FROM, with no named field in the count clause. COUNT() must be the only element in the SELECT list.</para> /// </summary> /// <param name="queryString">SOQL query string starting with SELECT COUNT() FROM</param> /// <param name="queryAll">True if deleted records are to be included</param> /// <returns>The <see cref="Task{Int}"/> returning the count</returns> public async Task <int> CountQuery(string queryString, bool queryAll = false) { // https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_count.htm // COUNT() must be the only element in the SELECT list. Dictionary <string, string> headers = HeaderFormatter.SforceCallOptions(_clientName); if (!queryString.Replace(" ", "").ToLower().StartsWith("selectcount()from")) { throw new ForceApiException("CountQueryAsync may only be used with a query starting with SELECT COUNT() FROM"); } using (var httpClient = new HttpClient()) { var jsonClient = new JsonClient(_accessToken, httpClient); var uri = UriFormatter.Query(_instanceUrl, _apiVersion, queryString); var qr = await jsonClient.HttpGetAsync <QueryResult <object> >(uri, headers); return(qr.TotalSize); } }
//soql /// <summary> /// Retrieve records using a SOQL query. /// <para>Will automatically retrieve the complete result set if split into batches. If you want to limit results, use the LIMIT operator in your query.</para> /// </summary> /// <param name="queryString">SOQL query string, without any URL escaping/encoding</param> /// <param name="queryAll">True if deleted records are to be included</param> /// <returns>List{T} of results</returns> public async Task <List <T> > Query <T>(string queryString, bool queryAll = false) { #if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); #endif try { Dictionary <string, string> headers = HeaderFormatter.SforceCallOptions(_clientName); var queryUri = UriFormatter.Query(_instanceUrl, _apiVersion, queryString, queryAll); using (var httpClient = new HttpClient()) { JsonClient client = new JsonClient(_accessToken, httpClient); List <T> results = new List <T>(); bool done = false; string nextRecordsUrl = string.Empty; //larger result sets will be split into batches (sized according to system and account settings) //if additional batches are indicated retrieve the rest and append to the result set. do { if (!string.IsNullOrEmpty(nextRecordsUrl)) { queryUri = new Uri(new Uri(_instanceUrl), nextRecordsUrl); } QueryResult <T> qr = await client.HttpGetAsync <QueryResult <T> >(queryUri, headers); #if DEBUG Debug.WriteLine(string.Format("Got query resuts, {0} totalSize, {1} in this batch, final batch: {2}", qr.TotalSize, qr.Records.Count.ToString(), qr.Done.ToString())); #endif results.AddRange(qr.Records); done = qr.Done; nextRecordsUrl = qr.NextRecordsUrl; if (!done && string.IsNullOrEmpty(nextRecordsUrl)) { //Normally if query has remaining batches, NextRecordsUrl will have a value, and Done will be false. //In case of some unforseen error, flag the result as done if we're missing the NextRecordsUrl //In this situation we'll just get the previous set again and be stuck in a loop. done = true; } } while (!done); #if DEBUG sw.Stop(); Debug.WriteLine(string.Format("Query results retrieved in {0}ms", sw.ElapsedMilliseconds.ToString())); #endif return(results); } } catch (Exception ex) { Debug.WriteLine("Error querying: " + ex.Message); throw ex; } }