Function Exceptions

You put the code in a try catch. If it bombs in the try, then you hit the catch, where you send back the exception and make success false.

this works for both, you return the information both ways.

That depends on what you are doing I guess. I haven’t done anything yet where one step affects the next, and if it did, I probably wouldn’t continue at all regardless of the exception. But that’s really going to be on a case by case basis.

After the discussion about SPAs and API Keys AND my current compulsion with Zero Trust Architecture, I’ve been investigating a different architecture.

The idea is to wrap an Epicor Function in lightweight Azure Function. This is a pure consumption model. No worries about patching servers; it auto-scales, pay only for what you use with a free quota every month. Then put the Azure Function behind Azure API Management.

The benefits:

  • Aligns with Zero Trust Principles (segmentation, identity, assume breach)
  • Works with Single Page Applications
  • Clients can now utilize the standard HTTP Status Codes
  • Uses Active Directory for Identity - including 3rd parties if necessary and Access Management
  • Enables Active Directory Conditional Access for sensitive operations
  • API-Key is secured in a Azure Key Vault or Secret Store and never exposed to the client. Easy key rolling.
  • Rate Limiting
  • IP Filtering
  • CORS protection without modifying Epicor’s Web Config
  • Enable cache responses where reasonable
  • Better logging for your Security Information and Event Management (SIEM)

This should work with SaaS, private cloud, and on prem organizations.

4 Likes

Thanks for the info Mark, I am playing around with some AI stuff right now in azure and will start to make an application soon.

Thinking about function app or power app maybe or pushing the model to an IoT device so everything is done locally, no need to expose anything outside the domain.

Azure is fascinating.

1 Like

@slitzau would you be willing to post the code for the foreach loop that calls your function?

@Banderson I have this function and I am having trouble calling it from custom code widget in a BPM. Do you know what I am doing wrong?

Full disclosure I don’t know what I am doing with this call.

Why you casting your params to tuples?

I have no clue, every example I see on here of people calling functions from C# are using this…

should I just pass the params as is?

Yes :wink:
Tuple types - C# reference | Microsoft Docs

1 Like

Aaron, didn’t even care to look at the tuples… I just thought epicor was expecting the params like this for some reason… As if a function call needed this.

Much appreciated! :smiley:

1 Like

@utaylor I have two functions, one which loops through Quotes based on a criterion for closing and then loops through the open Tasks. For each open Task it is doing the call to the other function to complete the Task, marks as WON and complete. Here is the statement

this.EfxLib.TASKS.TaskWon(t.Key1, t.TaskSeqNum);

t.Key1 is the QuoteNum I am passing

1 Like

Right on Scott, I am doing something similar with PO lines!

Thanks for your help and idea!

Background, I am running an updatable BAQ with advanced BPM update functionality. I have a BPM on Update.Preprocessing that has custom code widget that loops through each row in the ttResults where row mod = “u” and then calls my function that updates the unir price on the PO line.

Anyone know why when I update one row in my function call works fine in my foreach loop, but the second I try and process two rows I get this message: I can update both of the records individually just fine… @Aaron_Moreng @slitzau @josecgomez @Banderson

Correlation ID: a297fa1b-df36-4cd6-9213-df8c11946b86
Description: This is a duplicate entry of an existing record
Program: Epicor.Ice.dll
Method: UpdateRow
Line Number: 1285
Column Number: 21
Table: PODetail

So this is odd and annoying but I recall recently we had a weird issue where the “BO” cached the last record on a loop basically it doesn’t clean up properly and caused this issue.
The solution (annoyingly enough) is to re-instanciate the BO on each loop.

So instead of making a BO then looping
you loop and inside the loop the first thing you do is instanciate a bo and make your calls.

1 Like

Jose,

I am looping through the ttResults in the baq.

For each result that is updated I then pass its PO Num and PO line to the function and the function updates the unit price on that PO line.

I am not instantiating any business object to make these updates.

Maybe I am misunderstanding something.

Can you show your code? It’s kind of hard to trouble shoot without it.

Are you saying that you are instantiating the BO in the function? And then calling the function every time you loop? If that’s the case, then yes it should work, theoretically.

I will show the code.

Here is the Code for the advanced bpm on the updateable BAQ:

foreach(var row in (from row2 in ttResults where row2.RowMod == “U” select row2))
{

int PO = Convert.ToInt32(row.POHeader_PONum);
int POLine = Convert.ToInt32(row.PODetail_POLine);
decimal newdocunitprice = Convert.ToDecimal(row.PODetail_DocUnitCost);

this.InvokeFunction(“UpdatePO”,“UpdateApprovedPO”,PO,POLine,newdocunitprice);

}

Here is the function it is calling:

Have you tried different combinations of rows with the same PO? Different PO? Does it always fail on the second row no matter what?

Never mind, it updates the first row not the second.