D365 Chain of Command Extension and Event Handler Generator
Extending standard D365 Finance and Supply Chain code without overlayering is done through class extensions that wrap methods and through event handlers. This generator creates the skeletons so you can concentrate on the business logic.
Fill in
Used in the extension class name so it stays unique.
Leave empty if the method has no parameters, for example: str _id, int _qty
For methods with a return value use for example: boolean ret = next validate(_id);
1. Class extension with chain of command
[ExtensionOf(classStr(SalesFormLetter))]
final class SalesFormLetter_Contoso_Extension
{
public void run([Parameter list])
{
// Logic before the base method
next run();
// Logic after the base method
}
}2. Table data event handlers
class SalesTable_Contoso_EventHandlers
{
[DataEventHandler(tableStr(SalesTable), DataEventType::Inserting)]
public static void SalesTable_onInserting(Common _sender, DataEventArgs _e)
{
SalesTable rec = _sender as SalesTable;
// Set defaults on the record before it is inserted
}
[DataEventHandler(tableStr(SalesTable), DataEventType::ValidatingWrite)]
public static void SalesTable_onValidatingWrite(Common _sender, DataEventArgs _e)
{
SalesTable rec = _sender as SalesTable;
ValidateEventArgs args = _e as ValidateEventArgs;
// args.parmValidateResult(false) to block the write
}
}3. Table extension wrapping a table method
[ExtensionOf(tableStr(SalesTable))]
final class SalesTable_Contoso_Extension
{
public void insert()
{
// Logic before insert
next insert();
// Logic after insert
}
}Chain of command wrappers must be in a final class and call next. Unless the target method is marked Replaceable or Wrappable, the next call must be unconditional at the top level of the wrapper. Private methods cannot be wrapped, and methods must be public or protected and not static unless the base is static. Check the Microsoft documentation for your release for current rules.
Review your extension strategy
Share your list of planned customizations and we can flag which could be configuration, reports or integration instead.
Optional. The tool and every export work without this. No spam.
How to use it
Enter the class you want to extend, a suffix that identifies your model, and the method signature you want to wrap. Provide the exact next line, including the return assignment if the method returns a value. Copy the block into a new class in your own model. Build, then debug with a breakpoint in the wrapper to confirm the order of execution relative to other extensions.
- Match the modifier, return type and parameters of the base method.
- Name the class ClassName_Suffix_Extension.
- Keep wrappers thin and move logic into helper classes.
Rules of chain of command
The extension class must be marked final and decorated with ExtensionOf. The wrapper method has the same signature as the base method, without the static keyword unless the base is static. The platform requires you to call next, and by default the call must not sit inside a condition. The attribute Replaceable on the base method relaxes this so that the call may be conditional. Methods marked Wrappable false cannot be wrapped at all.
Events versus chain of command
Use a data event handler when you only react to a table event, such as inserting or validating a write. Use chain of command when you need to add logic around a method, change a parameter or return value, or run before and after the base. Both are supported and can coexist, but order between multiple extensions is not guaranteed, so avoid logic that depends on running before another extension.
Common mistakes
Teams frequently wrap too much and create hidden dependencies between models. Others forget that the extension has access to protected members only through the this reference and cannot see private members.
- Forgetting final on the class.
- Putting next inside an if block without Replaceable.
- Writing long business logic inside the wrapper instead of a helper class.
- Using the same class name in two models without a suffix.
Frequently Asked Questions
What is chain of command in D365 F&O?
It is the extension mechanism that lets you wrap a public or protected method of a class, table or form in a final extension class, run your logic before and after, and call next to run the base method and other extensions.
Why do I get an error that next must be called?
The compiler requires wrapper methods to call next unconditionally at the top level, unless the base method is marked Replaceable. Move the call out of the condition, or add logic around the call instead of skipping it.
Can I wrap private methods?
No. Private methods cannot be wrapped. Wrappable methods must be public or protected. If you need access to private logic, consider an event handler, a pre or post event, or raising a request with Microsoft to expose an extensibility point.
Should I use events or chain of command?
Use data events for reacting to table events and delegates for published hooks. Use chain of command when you need to wrap a method and control logic around the base call. Prefer the lightest option that satisfies the requirement.
If you want help planning extensions versus configuration for a D365 project, Netray can review your fit and gap list and suggest where to avoid customization.
Related Tools
D365 F&O X++ Select Statement Generator
Fill in a table, a filter field and a value to produce a while select, a Query API version and a set-based update_recordset in X++.
Microsoft DynamicsD365 F&O Fit Gap Analysis Worksheet
Editable fit gap worksheet that records requirements, responses, effort and cost with running totals.
Microsoft DynamicsD365 F&O Implementation Health Assessment
Ten-question self-assessment of customization load, update discipline, security, data quality and reporting for a D365 F&O environment.
Microsoft DynamicsD365 F&O Inventory Dimensions Reference
Lookup table of the product, storage and tracking inventory dimensions in D365 F&O and the dimension group flags that control them.
More Microsoft Dynamics tools
See all- D365 F&O OData URL Builder
- D365 Data Management Import Worksheet Template
- D365 Batch Job Checklist
- D365 Security Role Design Worksheet
- D365 One Version Update Test Checklist
- D365 Finance and Supply Chain Functional Design Document Template
- D365 Finance and Supply Chain Fit-Gap Analysis Worksheet
- D365 Finance and Supply Chain Data Migration Mapping Worksheet
- D365 Finance and Supply Chain Cutover Plan Template