This is my situation. I need to send a couple values to a specific endpoint when a customer record is added or updated. My thought is to use a GetNewCustomer Method Directive of the Customer table and based on that trigger, use the Execute Custom Code (C#) call of the Post-Processing BPM.
I’ve not done a lot of BPM’s so:
How do I get the specific field values from the Customer table when a record is added or updated.
Is using the Execute Custom Code call the proper way to send/POST my values to the endpoint?
Yes, I have done what you describe with a BPM on the Update method that detects when a row is added or updated. You can use the custom code widget to send a request via HttpClient.
However, I think Automation Studio makes this a lot easier to do if you have that available.
Oh, really? Thanks for the tip. I don’t think we have that but, I’ll check.
Did you use C# to do this type of process? I’ve got some basic C# code I created but it keeps telling me declarations aren’t allowed. I have my usings in the proper place … but I can’t declare a variable in the code?
I think you are on too old of a version if your profile is correct.
Yes, all c#
Here’s a small snippet of the code I’m using. Note that you will want your code block to be asynchronous so it doesn’t impede the execution of the business logic.
// New http client
using (var client = new System.Net.Http.HttpClient(handler))
{
// Set token
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "abc123");
// Add company and plant header
client.DefaultRequestHeaders.Add("Company", CompanyID);
client.DefaultRequestHeaders.Add("Plant", callContextClient.CurrentPlant);
// New message
using (var httpRequestMessage = new HttpRequestMessage(new HttpMethod(Method), requestUrl))
{
// Set content
if (string.IsNullOrEmpty(Content) == false)
{
httpRequestMessage.Content = new StringContent(Content ?? "", Encoding.UTF8, "application/json");
Ice.Diagnostics.Log.WriteEntry(Content);
}
try
{
// Send response
using (var response = client.SendAsync(httpRequestMessage).GetAwaiter().GetResult())
{
// Get content
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
// Set result content
output = content;
// Ensure success
response.EnsureSuccessStatusCode();
}
}
catch (Exception ex)
{
throw new BLException("Exception from request to API: " + ex.Message + " | " + output, ex);
}
}
}
System.Net.Http.HttpClient may not be available in your version, so you may have to add it as an external library. Just go download the latest .dll from .nuget that is compatible.
You can also do this with Change Data Capture (CDC) inside Kinetic. There are a couple of things to set up, but it effectively uses the webhooks process - something is listening for it and then reacts. You are using Mulesoft, but same thing as Epicor’s Workato solution.
You should check out the CDC stuff - it can send a lot and they are adding more rules/events in each release.
We did exactly this - Epicor → Mulesoft → SalesForce.
The approach was to create an audit field to record when specific customer fields were updated. This is triggered by a Customer.Update pre-processing method directive.
The function on a four hourly schedule via the ‘Schedule Epicor Function’ screen.
The function uses a BAQ to return all customer records hat have been updated between the last successful run datetime of the interface and the datetime that the current run started.
The exact fields returned by the query were defined by the integration mapping exercise.
Within the function the BAQ is called an results returned, the results are then converted into JSON and posted to end point in a custom code widget.
WebRequest request = WebRequest.Create (SFURL+"accounts");
var username = SFUserName ;
var password = SFPassWord ;
string encoded = System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1")
.GetBytes(username + ":" + password));
request.Headers.Add("Authorization", "Basic " + encoded);
request.Headers.Add("client_id", SFClientID);
request.Headers.Add("client_secret", SFClientSc);
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string oResult = Newtonsoft.Json.JsonConvert.SerializeObject(tsRetBAQ);
NoRecs = tsRetBAQ.Tables[0].Rows.Count;
payLoad = oResult;
byte[] byteArray = Encoding.UTF8.GetBytes (oResult);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/json; charset=utf-8";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream ();
// Write the data to the request stream.
dataStream.Write (byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close ();
// Get the response.
WebResponse response = request.GetResponse ();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream ();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader (dataStream);
// Read the content.
output = reader.ReadToEnd ();
// Clean up the streams.
reader.Close ();
dataStream.Close ();
response.Close ();
I use a UD table to log payload and responses.
As this is a function you can test it using Swagger, which is a plus. Also, you can run the BAQ independently to check that data is been returned.
// ID variable
string id = row.WebIDColumn_c;
// JSON body
var json = new
{
CustNum = row.CustNum,
};
string jsonBody = JsonConvert.SerializeObject(json);
// Create a new RestClient object
var client = new RestClient("https://api.yourdomain.co.uk/");
// Create a new RestRequest object
var request = new RestRequest($"users/{id}/approve", Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("blahahblah@example.com:435345345345")));
request.AddParameter("application/json", jsonBody, ParameterType.RequestBody);
// Send the request and wait for the response
var response = client.Execute(request);
if (response.IsSuccessful)
{
// Successful response
Ice.Diagnostics.Log.WriteEntry("Successful response: " + response.StatusCode);
}
else
{
// Unsuccessful response
Ice.Diagnostics.Log.WriteEntry("Error: " + response.StatusCode);
}
I’ve not either but I did a deep dive researching it so I could interface with our new HR/Payroll system via Workato. Never got back to that project but it’s on the list for this year
btw - it’s also the background processing for Collaborate which is why we have it turned on and running.