Epicor BPM Custom Code Block Generator (C# for Method Directives)
Most Epicor BPM logic can be built with widgets, but real rules eventually need a custom code block. This generator gives you correct C# skeletons for the three patterns developers write most: validating temp table rows, looking up database records, and showing messages.
Fill in
Validate new or changed rows (pre-processing)
foreach (var ttOrderHed in ttOrderHeds.Where(r => r.RowMod == "A" || r.RowMod == "U"))
{
if (string.IsNullOrEmpty(ttOrderHed.PONum))
{
throw new Ice.BLException("PO number is required for this customer.");
}
}Lookup against the database
foreach (var ttOrderHed in ttOrderHeds.Where(r => r.RowMod == "A" || r.RowMod == "U"))
{
var rec = Db.Customer
.Where(x => x.Company == Session.CompanyID && x.CustNum == ttOrderHed.CustNum)
.FirstOrDefault();
if (rec != null)
{
string value = rec.CustID;
// Use value here
}
}Information message instead of a hard stop
this.PublishInfoMessage(
"PO number is required for this customer.",
Ice.Common.BusinessObjectMessageType.Information,
Ice.Bpm.InfoMessageDisplayMode.Individual,
"ttOrderHed",
"PONum");Syntax can vary between Epicor 10 and Kinetic releases, and the Db context and temp table names depend on the business object the directive is attached to. Confirm field names and types in the BPM Designer's variable list and test in a pilot company before enabling in production. RowMod values: A added, U updated, D deleted.
Review my Epicor BPMs before an upgrade
Optional: expert review of BPM and customization risk.
Optional. The tool and every export work without this. No spam.
How to use the generator
Open your method directive in the BPM Designer, add a Custom Code block, and paste the relevant snippet after replacing names using the fields above. Set the temp table and collection to match the business object, for example ttOrderHeds on SalesOrder.Update. Use pre-processing directives for validation that must stop the save, and post-processing for work that should happen after the data is written.
Understanding the patterns
Epicor passes changed data to a directive as temp tables. The RowMod column shows the change: A for added, U for updated, D for deleted. Looping only those rows avoids processing untouched records. Db gives LINQ access to tables, and Session.CompanyID scopes queries to the current company. Ice.BLException stops the transaction and shows the text to the user, while PublishInfoMessage warns without blocking.
- Throw Ice.BLException to block the save
- PublishInfoMessage to inform without stopping
- Always filter Db queries on Company
- Check RowMod so you handle only the rows that changed
Common mistakes
Developers often loop all rows including unchanged ones, throw exceptions in post-processing after data is saved, or query the database inside nested loops. Forgetting the Company filter returns the wrong record in multi-company systems. Keep logic small, comment why the rule exists, and move reusable code into the function library. Test with add, update and delete paths, and with API and UI callers.
Frequently Asked Questions
Should validation be pre- or post-processing?
Use pre-processing for validation you want to block the save, since nothing is written yet. Post-processing runs after the base method, so exceptions there can leave a confusing state. Use post-processing for follow-up actions.
What does RowMod mean?
RowMod marks the type of change on a temp table row. A is an added row, U is updated, D is deleted, and blank means unchanged. Filter on it so your rule runs only for rows the user actually touched.
Can I call this code from several directives?
Not directly. For reuse, put the logic in a function in the Function Library and call it from each directive. That keeps rules in one place and makes upgrades easier to test.
Why does my code compile in Designer but fail at run time?
Common causes are null values from lookups, wrong field names on the temp table, or a Db query that returns nothing. Add null checks and test with realistic data in a pilot company.
Netray's AI agents can review BPM and customization code and help plan Epicor upgrades, with private on-prem models available.
Related Tools
Epicor BPM Directive Types Reference
Lookup table of Epicor BPM directive types, when each runs, whether it can stop a save, and typical use.
EpicorEpicor Business Object Service Reference
Lookup table of common Erp.BO services with their main table, primary key and standard method names.
EpicorEpicor BAQ OData REST URL Builder
Builds Epicor REST v2 OData URLs and curl commands for BAQs and business object services, with API key header and filters.
EpicorEpicor Kinetic Upgrade Readiness Assessment
Ten questions scoring how ready your customizations, BPMs, reports and integrations are for an Epicor upgrade.
More Epicor tools
See all- Epicor Kinetic Customization Change Request Form Template
- Epicor Kinetic Go-Live Cutover Plan Template
- Epicor Kinetic User Access Request Form Template
- Epicor Kinetic BPM Directive Inventory Worksheet
- Epicor Kinetic Scheduled Task Register Worksheet
- Epicor Kinetic Custom Report Inventory Worksheet
- Epicor Kinetic Data Migration Mapping Worksheet
- Epicor Kinetic Data Load Effort Calculator
- Epicor Business Object Services Reference