Error with external REST call from BPM

I have a Function that calls our Dayforce API and then terminates an employee if they are termed in our Dayforce system. I am getting the below error. the main issue is Cannot perform runtime binding on a null reference. not sure where in the code I have a null value that is causing the issue.

Any help is appreciated.

Exception executing library 'DayForce' function 'termEmplolyee':
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot perform runtime binding on a null reference
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at EFx.DayForce.Implementation.termEmplolyeeImpl.Run()
   at Epicor.Functions.FunctionBase`3.Run(TInput input) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Internal\Lib\Epicor.Functions.Core\FunctionBase.cs:line 75
   at EFx.DayForce.Implementation.termEmplolyeeImpl.AdapterRun(Object[] input)
   at Ice.Internal.Task.ScheduledFunction.ExecuteFunction.RunFunction(IFunctionAdapter functionAdapter, Object[] parameters) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Internal\Task\ScheduledFunction\ExecuteFunction.cs:line 128
   at Ice.Internal.Task.ScheduledFunction.ExecuteFunction.RunProcess(Int64 instanceTaskNum, String outputFileName) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Internal\Task\ScheduledFunction\ExecuteFunction.cs:line 57
   
   Program Ice.Services.Lib.RunTask raised an unexpected exception with the following message: RunTask:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot perform runtime binding on a null reference
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at EFx.DayForce.Implementation.termEmplolyeeImpl.Run()
   at Epicor.Functions.FunctionBase`3.Run(TInput input) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Internal\Lib\Epicor.Functions.Core\FunctionBase.cs:line 75
   at EFx.DayForce.Implementation.termEmplolyeeImpl.AdapterRun(Object[] input)
   at Ice.Internal.Task.ScheduledFunction.ExecuteFunction.RunFunction(IFunctionAdapter functionAdapter, Object[] parameters) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Internal\Task\ScheduledFunction\ExecuteFunction.cs:line 128
   at Ice.Internal.Task.ScheduledFunction.ExecuteFunction.RunProcess(Int64 instanceTaskNum, String outputFileName) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Internal\Task\ScheduledFunction\ExecuteFunction.cs:line 71
   at Ice.Core.TaskBase`1.StartProcess(Int64 instanceTaskNum, String outputFileName) in C:\_releases\ICE\ICE3.2.700.33\Source\Server\Internal\Lib\TaskLib\TaskBase\TaskBase.cs:line 83
   at Ice.Hosting.TaskCaller.InnerExecuteTask(IceDataContext newContext) in C:\_releases\ICE\ICE3.2.700.33\Source\Framework\Epicor.Ice\Hosting\TaskCaller\TaskCaller.cs:line 117
   at Ice.Hosting.TaskCaller.ExecuteTask() in C:\_releases\ICE\ICE3.2.700.33\Source\Framework\Epicor.Ice\Hosting\TaskCaller\TaskCaller.cs:line 59
   at Ice.Lib.RunTask.BpmFriendlyTaskLauncher.Run(String sessionIdPrefix, IceContext db, Action taskRunner) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Services\Lib\RunTask\BpmFriendlyTaskLauncher.cs:line 63
   at Ice.Services.Lib.RunTaskSvc.InnerRunTask(Int64 ipTaskNum, Boolean suppressTransaction) in C:\_Releases\ICE\ICE3.2.700.0\Source\Server\Services\Lib\RunTask\RunTask.cs:line 454
var client = "ServerCall";

var myDate = BpmFunc.Today(); 
var termOneDate = myDate.ToString("yyyy-MM-dd");
var termTwoDate = BpmFunc.Today().AddDays(-1).ToString("yyyy-MM-dd");

var restClient = new RestClient(client);
var request = new RestRequest($"/Api/zacs/V1/Employees?filterTerminationStartDate=2024-9-26&filterTerminationEndDate=2024-9-28", Method.GET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", "••••••");
request.AddHeader("Cookie", "_Classified");
request.AddParameter("Grant_type", "password");
request.AddParameter("CompanyId", "Classified");
request.AddParameter("Username", "Classified");
request.AddParameter("Password", "Classified");
request.AddParameter("Client_Id", "Dayforce.HCMAnywhere.Client");

var response = restClient.Execute(request);

this.output = response.Content.ToString();
dynamic json = JsonConvert.DeserializeObject<dynamic>(response.Content);

//Count to see how big the object is for our for loop
int count = json["Data"].Count;

this.output2 = count;

for(int i = 0; i < count; i++)
{
  var empXrefCode = json.Data[i].XRefCode.ToString();
  string newEmpId = empXrefCode.ToString();
  var employee = Db.EmpBasic.Where(x => x.Company == "TIMCO" && x.EmpID == newEmpId).FirstOrDefault();
  if(employee == null)
  {
    return;
  }
  if(employee.EmpStatus == "A")
  {
    employee.EmpStatus = "I";
  }
  if(employee.TermStatus_c == false)
  {
    employee.TermStatus_c = true;
  }
  
  employee.TermDate_c = BpmFunc.Today();
  Db.SaveChanges();
  
}

Is this code from a BPM Custom Code widget?

This is from a Function code block

Got it, just wanted to make sure since the title said BPM. Are you calling it with the InvokeFunction widget or with code from the BPM?

Calling it from the invoke function. I was planning on setting it on a schedule once I get working properly.

Can you share a screencap of the Invoke Function configuration? My first guess is that you’ve got the 2 response parameters this.output this.output2 in your function, and the BPM doesn’t know what to do with them.

sorry, I am running this from the schedule Epicor function.
image

Oh, that’s your problem right there. Remove both response parameters (temporarily). Schedule Epicor Function does not like response parameters.

Edit: Or create a separate function in the same library that calls the function you’re trying to test, and call that one with Schedule Epicor Function.

I’ve not had any problems?

I did make that change, removed all outputs and commented the code to remove them. Getting the same error. The error is very vague to me.

Generally, this means that a field does not have a value (null reference). Are you sure that all input parameters have values when calling the function?

1 Like

I do not have any parameters for the function (as seen below), I am not calling a BO. I am going to put null ref checks for all the data I am getting from the Dayforce API call and see if some of those are null.

forgot to attach the photo

Have you tried testing your function first without wiring it up to Dayforce? Many here use Postman but you can use any API testing tool. Once you know that works, then you can test the Dayforce API. Once comfortable, you can then wire the two together.

1 Like

Might not be a bad idea to catch your own errors and send them somewhere for logging as well :wink:

2 Likes

Update on trouble shooting
I am able to data back in postman sending a Get to: https://ServerName-services.dayforcehcm.com/Api/CompanyName/V1/Employees?filterTerminationStartDate=2023-10-1&filterTerminationEndDate=2023-10-31

I get back the data I thought I would, a JSON object with the data expected.

Then, I use Postman to to call my function in Epicor (Learned from a CodaBears Youtube video. https://www.youtube.com/watch?v=i1_brknfk20)
{{Server}}/DayForce/termEmplolyee is the post call to Epicor I use. I have added some exception handling in the code to get back an error message.

in postman i get: In Postman I get Sorry! Something went wrong. Please contact your system administrator. Correlation Id: c8dd6ead-eed1-4ef8-9a99-d5af56c8b2fe

if (response.StatusCode != HttpStatusCode.OK)
{
    throw new Exception($"API call failed with status: {response.StatusCode}, content: {response.Content}");
}

When this is in the code I get the following repsponse in the Log Files on the server when I look up the Correlation Id

![CDATA[System.Exception: API call failed with status: InternalServerError, content: {"requestId":"86c08097-9df3-4ead-bcc4-78fbba02baa8","processResults":[{"code":"SYS_FAIL","level":"ERROR","message":"Internal server error encountered while processing the following request: https://ServerName/Api/Company/V1/Employees?filterTerminationStartDate=2023-10-1&filterTerminationEndDate=2023-10-31&Grant_type=password&CompanyId=COmpany&User=UserName&Password=Password&Client_Id=Dayforce.HCMAnywhere.Client","details":{}}]}
if (response.Content == null)
{
    throw new Exception("Response content is null. Check the API request.");
}


this.output = response.Content.ToString();
dynamic json = JsonConvert.DeserializeObject<dynamic>(response.Content);

if (json == null || json.Data == null)
{
    throw new Exception("Deserialized JSON is null or does not contain 'Data'.");
}

If I leave out the first check, The server logs say that Deserialized JSON is null or does not contain ‘Data’ so I am guessing there is an issue with it communicating with the DayForce API.

I had the code working in our Pilot environment, then moved it to Production where it stopped working, Had to work on something different for a couple weeks and we restored Pilot to a newer image and the code that was working is no longer.

Any ideas would be appreciated.

Post the whole code.

Also did you double check your auth?

Im sorry, Did I check the Auth for Epicor or DayForce?
I took the code sample from postman and modified it to work from Epicor.

I am able to get the data when making the postman call with the Username and Password that we have for the system. I feel like I am missing 1 little thing for this to work. but I have changed all that I suspect would be the issue.

var client = "https://Classified.dayforcehcm.com";

var myDate = BpmFunc.Today(); 
var termOneDate = myDate.ToString("yyyy-MM-dd");
var termTwoDate = BpmFunc.Today().AddDays(-1).ToString("yyyy-MM-dd");

var restClient = new RestClient(client);
var request = new RestRequest($"/Api/zacs/V1/Employees?filterTerminationStartDate=2023-10-1&filterTerminationEndDate=2023-10-31", Method.GET);


request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", "••••••");
request.AddHeader("Cookie", "_abck=Classified");
request.AddParameter("Grant_type", "password");
request.AddParameter("CompanyId", "Classified");
request.AddParameter("User", "Classified");
request.AddParameter("Password", "Classified");
request.AddParameter("Client_Id", "Dayforce.HCMAnywhere.Client");

var response = restClient.Execute(request);

if (response.StatusCode != HttpStatusCode.OK)
{
    throw new Exception($"API call failed with status: {response.StatusCode}, content: {response.Content}");
}

if (response.Content == null)
{
    throw new Exception("Response content is null. Check the API request.");
}


this.output = response.Content.ToString();
dynamic json = JsonConvert.DeserializeObject<dynamic>(response.Content);

if (json == null || json.Data == null)
{
    throw new Exception("Deserialized JSON is null or does not contain 'Data'.");
}

After this, I am writing to Epicor DB to term an employee, but that part of the code is not where the error is.

try it without that slash in front $"Api"

Same Error: “code”:“SYS_FAIL”,“level”:“ERROR”,“message”:"Internal server error encountered while processing the following request:

Would have been both mad and happy if that was the fix.

1 Like

You said it works in postman?

If so, show us how that is set up.