public async Task <MimeMessage> RunAsync(MimeMessage message, ISessionContext context, IMessageTransaction transaction, CancellationToken cancellationToken) { _logger?.Log(LogLevel.Information, "Injecting headers into message"); try { //Add headers to the top of the message var bodyTextParts = message.BodyParts.OfType <TextPart>().ToList(); var htmlBody = bodyTextParts.LastOrDefault(btp => btp.IsHtml); var textBody = bodyTextParts.LastOrDefault(btp => !btp.IsHtml); if (htmlBody != null) { var bodyTagLocation = htmlBody.Text.IndexOf("<body>", StringComparison.OrdinalIgnoreCase); var insertLocation = bodyTagLocation == -1 ? 0 : bodyTagLocation + 6; htmlBody.Text = htmlBody.Text.Insert(insertLocation, $"\n{HeaderFormatter.GetHtmlHeaders(message)}"); } if (textBody != null) { textBody.Text = $"{HeaderFormatter.GetPlainTextHeaders(message)}\n{textBody.Text}"; } } catch (Exception exception) { _logger?.Log(LogLevel.Error, exception, "Error injecting headers into message"); //Don't throw, continue routing message } return(await Task.FromResult(message).ConfigureAwait(false)); }
/// <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 QueryOptionsHeaderMinException() { Assert.Throws <ArgumentException>(() => { var customHeaders = HeaderFormatter.SforceQueryOptions(0); }); }
public void AutoAssignHeader() { KeyValuePair <string, string> header = HeaderFormatter.SforceAutoAssign(false); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("Sforce-Auto-Assign: FALSE", result); }
public void QueryOptionsHeader() { KeyValuePair <string, string> header = HeaderFormatter.SforceQueryOptions(1000); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("Sforce-Query-Options: batchSize=1000", result); }
public void IfModifiedSinceHeader() { DateTimeOffset date = new DateTimeOffset(2015, 3, 23, 0, 0, 0, 0, new TimeSpan(0)); KeyValuePair <string, string> header = HeaderFormatter.IfModifiedSince(date); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("If-Modified-Since: Mon, 23 Mar 2015 00:00:00 GMT", 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 Property(Type objectType, string propertyName, PropertyFormatter formatter, HeaderFormatter headerFormatter, int order = 0) { if (propertyName == null) throw new ArgumentNullException("propertyName"); if (formatter == null) throw new ArgumentNullException("formatter"); if (headerFormatter == null) throw new ArgumentNullException("headerFormatter"); PropertyName = propertyName; _propertyReader = new PropertyReader(objectType, propertyName); HeaderFormatter = headerFormatter; ValueFormatter = formatter; Order = order; }
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); }
public void QueryOptionsHeader() { Dictionary <string, string> customHeaders = HeaderFormatter.SforceQueryOptions(1000); Assert.Single(customHeaders); var header = customHeaders.First(); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("Sforce-Query-Options: batchSize=1000", result); }
public void AutoAssignHeader() { Dictionary <string, string> customHeaders = HeaderFormatter.SforceAutoAssign(false); Assert.Single(customHeaders); var header = customHeaders.First(); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("Sforce-Auto-Assign: FALSE", result); }
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; } }
public void IfModifiedSinceHeader() { DateTimeOffset date = new DateTimeOffset(2015, 3, 23, 0, 0, 0, 0, new TimeSpan(0)); Dictionary <string, string> customHeaders = HeaderFormatter.IfModifiedSince(date); Assert.Single(customHeaders); var header = customHeaders.First(); string result = string.Format("{0}: {1}", header.Key, header.Value); Assert.Equal("If-Modified-Since: Mon, 23 Mar 2015 00:00:00 GMT", result); }
private void AddData(IList <string> header, int index, string value) { string fieldName = HeaderFormatter.To_Field_Name(header[index]); EntityField entityField = Field(fieldName); if (entityField == null) { logger.DebugFormat("Could not find field: {0} in {1}", fieldName, GetType()); } else { entityField.SetValue(value); } }
/// <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); } }
public async Task <MimeMessage> RunAsync(MimeMessage message, ISessionContext context, IMessageTransaction transaction, CancellationToken cancellationToken) { _logger?.Log(LogLevel.Information, "Adding headers as an attachment"); try { var stream = new MemoryStream(); var streamWriter = new StreamWriter(stream); streamWriter.Write(HeaderFormatter.GetPlainTextHeaders(message)); streamWriter.Flush(); stream.Position = 0; var attachment = new MimePart("text", "plain") { Content = new MimeContent(stream), ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), ContentTransferEncoding = ContentEncoding.Base64, FileName = "OriginalHeaders.txt" }; //Add the attachment to the existing parent-level multipart if it exists. //Otherwise create a parent multipart and put the message body and attachment in it. if (message.Body is Multipart multipart) { multipart.Add(attachment); } else { message.Body = new Multipart("mixed") { message.Body, attachment }; } } catch (Exception exception) { _logger?.Log(LogLevel.Error, exception, "Error adding headers as an attachment"); //Don't throw, continue routing message } return(await Task.FromResult(message).ConfigureAwait(false)); }
/// <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); } }
public Property(Type objectType, string propertyName, PropertyFormatter formatter, HeaderFormatter headerFormatter, int order = 0) { if (propertyName == null) { throw new ArgumentNullException("propertyName"); } if (formatter == null) { throw new ArgumentNullException("formatter"); } if (headerFormatter == null) { throw new ArgumentNullException("headerFormatter"); } PropertyName = propertyName; _propertyReader = new PropertyReader(objectType, propertyName); HeaderFormatter = headerFormatter; ValueFormatter = formatter; Order = order; }
public virtual string ToHeader(FieldInfo fieldInfo) { return(IsAnEntity(fieldInfo) ? ((Entity)fieldInfo.GetValue(entity)).Header : HeaderFormatter.To_Header_Column(fieldInfo.Name) + ", "); }
private static void VerifyLineTwo(HeaderFormatter formatter) { Assert.AreEqual("Date: 02/10/2002 0:00:00", formatter.LineTwo); }
//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; } }
private static void VerifyLineOne(HeaderFormatter formatter) { Assert.AreEqual("Price: 22,4", formatter.LineOne); }