57% found this document useful (7 votes)
3K views

D365FO Extension Patterns

The document discusses extension patterns in Dynamics 365 for Operations. It covers how to extend tables, classes, forms, enums, EDTs and reports in a non-intrusive way through techniques like table extensions, class extensions, event handlers, and form controls. The best practices are to avoid changing method signatures or requirements, and to make extension names and elements unique to avoid conflicts. Extension methods must call the next method in the chain of command.

Uploaded by

Robert van Mill
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
57% found this document useful (7 votes)
3K views

D365FO Extension Patterns

The document discusses extension patterns in Dynamics 365 for Operations. It covers how to extend tables, classes, forms, enums, EDTs and reports in a non-intrusive way through techniques like table extensions, class extensions, event handlers, and form controls. The best practices are to avoid changing method signatures or requirements, and to make extension names and elements unique to avoid conflicts. Extension methods must call the next method in the chain of command.

Uploaded by

Robert van Mill
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

Dynamics 365

for operations
extension patterns
Prepared for
Microsoft Internal
Table of Contents
What is intrusive customization: .................................................................................................................. 4
Table Extension ............................................................................................................................................. 4
What is in scope: ....................................................................................................................................... 4
What is not in scope: ................................................................................................................................ 4
Best practice: ............................................................................................................................................ 4
Add a method to a table ........................................................................................................................... 4
Add a display or edit method to a table ................................................................................................... 5
Event handlers and delegates (hooks) ...................................................................................................... 7
Events listed inside the event node ...................................................................................................... 7
Pre and Post event handlers on public methods .................................................................................. 8
Subscribe existing delegates on table methods.................................................................................... 9
Class Extension ............................................................................................................................................ 10
What is in Scope:..................................................................................................................................... 10
What is not in scope: .............................................................................................................................. 10
Best practice: .......................................................................................................................................... 10
Extension class declarations ................................................................................................................... 10
Reason why it is marked as final ......................................................................................................... 10
Methods in extension class ................................................................................................................. 11
Add new method to existing class .......................................................................................................... 11
Instance methods................................................................................................................................ 11
Static methods .................................................................................................................................... 11
Add new state ......................................................................................................................................... 12
Instance state ...................................................................................................................................... 12
Static state .......................................................................................................................................... 12
Chain of Command ................................................................................................................................. 12
Wrapper methods must always call next............................................................................................ 12
The Hookable attribute ........................................................................................................................... 16
Final methods and the wrappable attribute ....................................................................................... 16
Method signatures .................................................................................................................................. 16
Option 1: Method overloading ........................................................................................................... 17
Option 2: Class state ........................................................................................................................... 17
Option 3: Disposable context .............................................................................................................. 18
Register a subclass for factory methods ................................................................................................. 20
Respond by using EventHandlerResult or types that implement IEventHandlerResult ......................... 21
EventHandlerResult ............................................................................................................................ 21
Accept and reject request/response scenarios .................................................................................. 21
Extend the RunBase class........................................................................................................................ 23
Limitations in class .................................................................................................................................. 27
Extension support for methods with DataMemberAttribute ............................................................. 27
Form Extension ........................................................................................................................................... 28
What is in scope: ................................................................................................................................. 28
What is not in scope: .......................................................................................................................... 28
Best practice: ...................................................................................................................................... 28
Form method .......................................................................................................................................... 29
Through chain of command ................................................................................................................ 29
Through pre-post event handlers ....................................................................................................... 29
Form Event .............................................................................................................................................. 31
Form Datasource method ....................................................................................................................... 32
Form Datasource field method ............................................................................................................... 33
Form Datasource Event........................................................................................................................... 36
Form control Event ................................................................................................................................. 38
Enum extensions ......................................................................................................................................... 40
EDT extensions ............................................................................................................................................ 41
Report extensions: ...................................................................................................................................... 41
Frequently used patter in upgrade: ............................................................................................................ 43
What is intrusive customization:
1. Don't change a method signature.
2. Don't change requirements for implementers of interfaces and table maps.
3. Don't change requirements for classes that are derived from abstract classes.
4. Don't reduce access modifiers for types or members.
5. Don't change constraints that are defined on a table or a data entity

Table Extension
What is in scope:
1. Adding new fields
2. Field groups
3. Indexes
4. Mapping
5. Relation
6. Add new fields to existing field groups
7. Change the label of a table field
8. Change the Created By, Created Date Time, Modified By, Modified Date Time (except inherited
table), country region codes properties etc.
9. Adding new methods by COC

What is not in scope:


1. You cannot delete any element from standard table
2. Unique indexes can't be changed
3. Mandatory property
4. Relation modification

Best practice:
a) Do not name the extension just <Element that is being extended>.Extension. For example, an
extension class that augments the custGroup table must not be named custGroup .Extension,
because the risk of conflicts is too high.

b) Fields, indexes, relations, and other metadata elements on extension elements must have a
name that is unique across both the element that is being extended and other extension
elements. Therefore, these metadata nodes must include a term, abbreviation, or prefix that
minimizes the risk of conflicts across models.

Add a method to a table


In Dynamics 365 for operations, we won’t be able to add the new method or modify the existing method to
the standard table or to an extension table. We can achieve this requirement by creating the extension class
for the table.
Example, a new field that is named MyInventLocationId was added to the InventTable table through
extension. A data event handler was also created for the Inserting event, and you must implement the logic
of filling the new field there. To encapsulate that action, you will create a new method on InventTable and
name that method defaultMyInventLocationId.
You can now add new methods to the augmentation class. These methods will then appear in IntelliSense for
variables of the InventTable type, just as if they were defined directly on the table. This behavior applies to
both static methods and instance methods.

Add a display or edit method to a table


The display and edit method modifiers are supported on table extensions.

Requirement is to add a display method in the standard table, it can be achieved either by creating a table
extension or static class.

Use of display method – form extension


To use this display method in the form \ Form list page – On form extension create a string control in the
form design and set the following properties.
Data source: SalesTable
Data Method: SASalesTableListPage_Extension::customerNameAlias
Cache Data Method: Yes

Result – Name is been added as display method on form.


Event handlers and delegates (hooks)
Note - We can write Chain of Command (Explained later in the document) for table methods like insert \
update \ delete, if they are already there in table else, we can use events on table. In PU17 we will have the
ability to overwrite methods that are not implemented in the derived classes yet.
Events listed inside the event node
Earlier AX versions, we could override the virtual methods of a table's base class to control the behavior that
occurred during table operations, such as when creating, reading, updating, or deleting. In the current
version, we instead use extensions to implement event handlers that are called from the base
implementations of the table methods.

There are already plenty of events (hooks) we can subscribe in AX and extend the existing functionality
without overlayering or overriding the function we need to extend. You can find those under the “Events”
node of the application objects. Subscription is as easy as right clicking and selecting “Copy event handler
method”, then you need to paste it into an eventHandlers class and write your own logic inside

Example - subscribe to the ‘Deleted’ event of the table

Note - that the object methods (like insert, update, init, write.) we used to override in the AX 2012 now
corresponds to two different events, as ‘Deleting’ and ‘Deleted’, and we no more call super() in our event
handler methods.

Execution of those compared to AX2012 works like below

On all events you subscribe you also have a parameter that contains an “event args” object for the
corresponding event. However, this parameter is not always the event args class you exactly need. They are
generally down casted to their most common base class (DataEventArgs for data related events or
FormEventArgs for events on the form root) and you need to cast it back to the args class you need.

Example
There are a lot of event handlers with down casted parameters like this one and it is impossible to list all of
them here. Please refer below reference link –

Reference - https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-
itpro/extensibility/customization-overlayering-extensions#table-extensions
Pre and Post event handlers on public methods
Beyond these events listed inside the Events node, there are Pre and Post event handlers which you can
subscribe to existing public methods and run your own logic before or after the original method is executed.
And it is possible to change the return type and access the method parameters using the XppPrePostArgs
parameter like the example below

Note – pre and post event handlers are not type safe. So, chain of command is recommended way for these
methods.
Subscribe existing delegates on table methods
There are already many delegate functions in table events section published by Microsoft.

Reference - https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-
itpro/extensibility/respond-event-handler-result
Class Extension
What is in Scope:
1. Public methods
2. Protected methods
3. Only methods that are defined in regular classes can be wrapped
4. Static methods
5. Instance state
6. Static State
7. Extension classes can wrap default parameters of method. However, the method signature in
the wrapper method must not include the default value of the parameter.

What is not in scope:


1. Private methods only accessible by defining wrappable or hookable attribute as true.
2. Methods that are defined in extension classes cannot be wrapped by augmenting the extension
classes.
3. Pre/Post eventhandler not supported for Protected method until hookable attribute is define as
true.

Best practice:
a) DO NOT name the extension of class simply as _MYExtension. Element name should be append
with _Extension. Example: MyClass_Extension or <classname>+ <model abbreviation>_extension
b) DO start the name of the extension class with the name of the type being augmented, and end it
with the term _Extension.

Extension class declarations

Extension classes are classes that are adorned with the ExtensionOf attribute and that also have a name that
has the _Extension suffix. (This restriction on the naming might be removed later.) The name of the
extension class is otherwise unimportant. The class augments the artifact that is specified in the ExtensionOf
attribute, as shown in the following example.

Reason why it is marked as final


Because the classes are instantiated by the runtime system, it's not meaningful to derive from the extension
class.
The classStr compile-time function must be used and has two purposes:
 It produces a compilation error if the MyClass class doesn't exist.
 The compile-time function that is used tells the compiler what kind of artifact is augmented. Artifact
names by themselves don't uniquely identify a given artifact to augment. For example, forms can
have the same names as tables, classes, and enums.
Any number of extension classes can augment a given artifact in a particular model. Extension classes are
never referenced directly by the programmer, only by the runtime system.
Methods in extension class
The public methods that are defined in extension classes provide additional functionality to the augmented
class in the context of the model where the extension class is defined. Only public methods are exposed in
this way. You can define private methods to help implement the public methods, but those private methods
aren't part of the effective class. Because extension classes are final, methods can't be marked as protected.

Add new method to existing class


Instance methods
Suppose we want to add a new method ExtensionMethod to the SalesCopying class.

The following example shows how to call the method in the model.

Static methods
Methods that are defined as public and static in the extension class are available as static methods on the
artifact that is augmented.

The following example shows how to call the method in the model.
Add new state
In addition to providing static and instance methods to an artifact, you can add instance state and static
state.

Instance state
Instance state, which is state that pertains to an instance of an artifact, can be specified on extension classes.
The following example defines a state that is named state.

The following example shows how to use state in your code.

Static state
Static state applies to the type instead of an instance of the type. The following example shows a static
extension state. Static constructors are the parameter-less static methods that are named typenew. Static
constructors can be defined on extension classes. It's guaranteed that the runtime system will call the
constructor before the first reference to the extension type.

Chain of Command
You can now wrap logic around methods that are defined in the base class that you're augmenting. You can
extend the logic of public and protected methods without having to use event handlers. When you wrap a
method, you can also access public and protected methods, and variables of the base class. it required use of
the next keyword create a Chain of Command (CoC) for the method.

Wrapper methods must always call next


Wrapper methods in an extension class must always call next, so that the next method in the chain and,
finally, the original implementation is always called. This restriction helps guarantee that every method in the
chain contributes to the result.

In the current implementation of this restriction, the call to next must be in the first-level statements in the
method body.
Here are some important rules:

 Calls to next can't be done conditionally inside an if \ else statement.


 Calls to next can't be done in while, do-while, or for loop statements.
 A next statement can't be preceded by a return statement.
 Because logical expressions are optimized, calls to next can't occur in logical expressions. At runtime,
the execution of the complete expression isn't guaranteed.

Now we can add pre and post functionality to extensible methods in a much easier and readable manner
than the previously used event handlers, also we are now able to access protected methods and variables
directly in the extended class without problems. Now let’s check how it works with an example.
Example of CoC
Create two classes, one is the base class of the other and add a method we want to extend called ‘testMe’.
Add Infolog calls inside the method to track the execution

Create a new model, add reference for the class model we created above, and add an extension class for our
child class.

The method we added here is the new chain of command definition. We use exactly the same notation as the
original method we are extending and add a mandatory “next” keyword to the call which will wrap our
extension code around the extended method. This next keyword separates the pre and post parts of our
extension and mandatory to be called inside the chain of command method. When you call next(), it checks
for other extensions in the queue and runs them in random order, lastly running the base code.
The advantage of chain of command is you can share the same method variables in the pre and post
(before/after next() call) or share the same tts block inside your COC method.
Example of CoC with return value
COC also supports return value and parameter modification of the extended method in a much more
readable manner. Extending a method with return value and parameters in COC is like below

Example
The Hookable attribute
If a method is explicitly marked as [Hookable(false)], the method can't subscribe to pre-events and post-
events by extenders. In the following example, anyMethod can't be subscribe to pre-events and post-events
by extenders in a class that augments anyClass1.

Final methods and the wrappable attribute


Public and protected methods that are marked as final can't be wrapped in extension classes. You can
override this restriction by using the Wrappable attribute and setting the attribute parameter to true
([Wrappable(true)]). Similarly, to override the default capability for (non-final) public or protected methods,
you can mark those methods as non-wrappable ([Wrappable(false)]).

In the following example, the doSomething method is explicitly marked as non-wrappable, even though it's a
public method. The doSomethingElse method is explicitly marked as wrappable, even though it's a final
method.

Method signatures
Method signatures are not extensible – and will not be. Extensible parameters would be intrusive – in so
many ways

 Breaks derived classes (signatures of overridden methods must match),


 Requires recompilation,
 No side-by-side support.
A method's signature is the contract between caller and method. When new parameters are added, then
callers can provide additional data that the method can act on. In isolation; a request for an extra parameter
makes no sense. An extra parameter will not help anyone unless someone is passing it in, and someone is
acting on it.
In the land of extensibility there are restrictions:
 You cannot change the places a given method is called, that would require overlayering. But you can
call the method from your own code (with control over the parameters).
 You cannot change the implementation of the method, that would require overlayering. But often
you can add logic pre/post or wrap using Chain-of-command.
With these constraints, here are some options:
Option 1: Method overloading
Scenario
You need to pass extra information from your code to an existing method and act on it in a pre/post handler.

Description
X++ doesn't support overloading methods – but you can mimic the behavior by creating a new method (with
new name) in an extension class. The extension method can take additional parameters and call the original
method; with your logic before and after calling the original method.

Example
Here is an example of "overloading" the insert method on CustTable. Notice the first 3 parameters are
identical to the parameters on the original insert() method.

Option 2: Class state


Scenario
You need to pass extra information from your code to a method on a class that is called via other method(s)
on the class.
Description
X++ now supports adding class state via an extension. You can use this to store the extra information.
Example
Here is an example adding state and wrapping a method.

Here is an example using this. The standard implementation of initFromItemOrCategory() calls


initFromInventTable().
Option 3: Disposable context
Scenario
You need to pass extra information from your code to a pre/post handler somewhere downstream.
Description
It can be tempting to store the extra information in a global cache or variable. There is a better approach,
which avoids stale data, and is type-safe. Create a singleton class for the context. The class must implement
System.IDisposable, so it is disposed when it goes out of scope. The receiving code can access the singleton
instance to extract the information.
Example
Here is an example of the context class:

Here is an example of the calling code:

Here is an example of the consuming code. The standard implementation of CustTable.Insert() calls
DirPartyTable::createNew() – the example uses Chain-of-command to wrap the createNew method, and then
accesses the context to get the information.
Caution
Transferring state from one arbitrary place to another using a global variable (which the context class is) can
lead to future logical errors – that can be very hard to detect and fix. Recommendation would be to limit the
usage to situations where the scope and consequences are manageable.
Register a subclass for factory methods
Reference
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/register-
subclass-factory-methods
Respond by using EventHandlerResult or types that implement IEventHandlerResult
EventHandlerResult
Delegate methods and delegate handler methods can be declared to support a request/response scenario,
where the delegate calling logic requests the subscribers to provide a response. To support this scenario the
EventHandlerResult class is most often passed as a parameter, and the delegate handler methods provide
their result using one of the result methods on the class. However, the EventHandlerResult class can only
contain a single result.

The EventHandlerResult class has an additional static constructor which ensures that the logic fails if more
than one subscriber provides a result. The new constructor is named newSingleResponse. When instantiating
an EventHandlerResult object using this method, the framework will throw an exception as soon as a second
delegate handler method attempts to provide a result.

The below example describe to provide a result from handler method.

Guidelines

 In general, the logic that is implemented in the delegate handler method should contain a condition
that verifies that the subscribing logic is responsible for providing a response. It should also include
logic to provide the response in the form of a result.
 When the delegate handler method must provide the response to an EventHandlerResult object
parameter, the subscribing logic might also contain logic to calculate or retrieve the result.
 When the condition and the response logic are implemented, the calculation of the result must occur
only when the condition is evaluated to true.
 All the subscribing delegate handler methods are run when a delegate is called. Therefore, you should
make sure that the overhead of running your method is as low as possible when the method isn't
responsible for providing a response. Therefore, make sure that the condition is evaluated to false as
quickly as possible when your delegate handler method isn't responsible for providing a result.

Accept and reject request/response scenarios

When using the EventHandlerAcceptResult class, the delegate handler method can only respond by calling
the accept method.
Method

Delegate

Subscriber method

When using the EventHandlerRejectResult class, only the reject method can be called.
The following example shows a delegate handler method that responds by using an
EventHandlerRejectResult object. To respond by using an EventHandlerRejectResult object, you can call the
reject method or the checkFailed extension method. If you use the checkFailed method, you can add a
warning message to the Infolog. Internally, the checkFailed method calls the reject method.
Method

Delegate

Subscriber

Reference
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/respond-
event-handler-result
Extend the RunBase class
How to extend the information shown on a RunBase-based dialog, and how to handle that information
once the user enters the necessary data. Also, how to preserve the user entered data, so that next time
the dialog is opened, it contains the last entries already populated. This is the typical pattern used across
all AX forms and is internally based on the SysLastValue table.

Suppose we want to extend the SysUserLogCleanup class. Out-of-the-box this class is deleting records
from the SysUserLog table. Let's imagine we want to archive these records to a different table before
they are deleted. The SysUserLogCleanup class is a RunBase class. The RunBase class has a dialog box,
where the user is prompted for parameters before the class is run. For this example, we will add a toggle
button control to the dialog box, get the value of the control, act on the value in the run method, and
make sure that the value is serialized via the pack and unpack methods. Serialization helps guarantee
that the user’s last selection is presented again if the dialog box is reopened. It also helps guarantee that
the settings are applied if the class is run in the background.
Reference
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/extend-
runbase-class

https://blogs.msdn.microsoft.com/mfp/2017/01/31/extending-class-state/
Limitations in class
Extension support for methods with DataMemberAttribute
Dave Froslie - DataMemberAttribute support is a platform request that has been made by several
partners. The request has some risk associated with it, and the best case is for it to be in PU19 which is
several weeks out - https://msdyneng.visualstudio.com/FinOps/_workitems/edit/199219.
Form Extension
What is in scope:
1. Add a new control.
2. Enable or disable a control.
3. Change the text or label property of a control.
4. Change a control's visibility.
5. Change a form's help text.
6. Change a form's caption.
7. Add a new data source.
8. Add a form part.
9. Implement the code in class as COC
a) Form methods
b) Form data source method (formdatasourcestr)
c) Form data source field method (formdatafieldstr)
d) Form data source control methods (formcontrolstr)

What is not in scope:


1. There is a limitation to handle the data source field control lookup.

Best practice:
a) Do not name the extension just <Element that is being extended>.Extension. or <Element that
is being extended>.Extension1… For example, an extension class that augments the
SalesParameters table must not be named SalesParameters.Extension, because the risk of
conflicts is too high and also it would be carry the upgrade cost.
Form method

Through chain of command


We can use class extensions to author X++ logic associated with form extensions. This allows the definition of
state variables accessible to form and control event handlers. It also allows overriding form methods without
overlayering code.

Example –
Form name – BOMRouteCopyDialog
Customization: CloseOk():

Using chain of command –

Through pre-post event handlers


Example –
Retrieve the CustAccount when opening the InventNonConformance Form
Find the form that you want to extend in the AOT

Open the “Methods” node and copy an event handler for the init()method from here.
Form Event
Extending form method example

Now we have another option to extend the init method on the form. Option one is to open the “Events” node
and hit “Copy event handler method” on the “OnInitialized” event. OnInitialized is a post
event, OnInitializing the opposite, a pre-event.

The difference is minimal, in both cases we will call args().record() from the FormRun object. When using the
post handler on the init method, we will have to get this FormRun object first, not a big thing, we have just to
call the getThis() method on the provided arguments of the handler.

Result – If we select a customer and hit “Non conformances” from the “SELL” tab on the CustTable form, we
will see the following Infolog.
Form Datasource method
Now PU20 onwards, you can wrapped the form data source methods, data source field methods and control
methods.

Note - "What about our custom-made methods, we can’t add those to an extension class if they are under a
datasource."
Answer - yes, you can add your custom methods (PU20) to DS on class extension. However, if there is any
problem with methods implementation please moved the method to form level with some tricks. So, the
pipeline is
 Move your custom methods from DS level to Form level
 Move your custom form-level code to Extension class
 Create eventHandlers for required events
 Call your custom method using formhasmethod()
Explained design below in Form Datasource field method
Form Datasource field method
Common customization task to override standard form data source field methods like jumpRef(), modified()
or validate().

Recommended approach in AX 7 is to avoid overlaying and use extensions as much as possible. To achieve
this new event were introduced. However, on form data source field level we have only 3 available events:

For example, we want to add custom jumpRef() and validate() methods to itemId field on sales order
form. First, we will create class to handle method overrides.
Then we will create new event handler class and subscribe to OnInitialized event of SalesLine data source.
Using this approach, you can override any data source field method.

Note – “Known” issue - doesn’t work for lookup method on datasource field.
Form Datasource Event
Form control Event
Below is the list of the Form > Design > control level event handler methods can be written - differs basing
on the data type the control (For Combo box/enum type the event will be different).

Example 1 –
Example 2 –

Let say in our example we will write the event handler for the form data source > Design > Control level >
Onlookup methods in the "LedgerJournalTransCustPaym" standard form.

 Open the Form > LedgerJournalTransCustPaym > Data Source (LedgerJournalTrans) > Design >
Control level > Property_AgreementId is the custom field added to LedgerJournalTrans. Expand the
Events (expand the events node). As shown in the above the screen shot.
 Right click on the Onlookup> copy the event handler method. Below is the screenshot.
Enum extensions
 You can extend any Enum that is marked extensible (IsExtensible=True) and
UseEnumValue = No

By extending an Enum, you can add new Enum values to it. It is important to keep the following in mind when
dealing with extensible Enums:

1. You cannot have X++ logic that depends on the integer value of Enum values (For example. If
(Enum1.v1 > Enum1.v2) ... is not supported for extensible enums)
2. When Enum values of extensible Enums are synchronized into the database:

 Integer values that belong to the baseline enum are deterministic. They come from the
metadata.
 Integer values that are an extension are generated during the synchronization process and
are not deterministic.

Best practice:
If your enum has many elements, such as more than 100, consider redesigning the solution instead of making
the enum extensible. If the enum is extensible, then adding more elements in the future might break
customer’s combined solution as the addition might exceed the limit.
EDT extensions
You can extend an EDT element in order to modify any of the following properties:

 Form help
 Label
 String size
 Help text

Note: For derived EDTs, string size can't be changed by an extension, because the IS-A relationship between
the EDTs will be broken.

How to manipulate number of decimal if number of decimals extensible is false.

You can manipulate by parent EDT.

Report extensions:
https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-
itpro/analytics/custom-designs-business-docs
Note: For maintainability purpose, maximum print management report is getting call by
getDefaultReportFormat instead of report name.

Add a delegate handler method to start to use your custom report. Extend
the getDefaultReportFormatDelegate method in your own custom class as below

Now you can extends the exiting controller class and use below code.
Option 1:

Alternatively, you can implement wrapper class with below code.


Option 2:

Note: if you faced an issue that the new report design was not being displayed even after
creating the above extension class (Option 1) and referring to the new report design, so you
can resolved this issue by adding the below outputReport method:
Frequently used patter in upgrade:

Pattern 1: Case structure

Example:

How to adjust new cheque Type.


Pattern 2: error handling in extension code
Pattern 3: Initialize the table fields value

Example:

Correct approach:

Go to initializeSalesPackingSlipHeader() and initialize your fields after next call.


Pattern 4: How to write COC form data source methods.

Limitation: We cannot invoke one of these methods in a chain of command wrapper somewhere else
because only the base code would be executed and COC code won’t be execute.

Example:
Pattern 5: How to cancel super call in from data source method before executing the standard validation.

Now you can call the COC for data source method and return true value.
Pattern 6:
Pattern 7: If method is predefine in table, you can write COC.
Pattern 8: form data source control level evend hndler

However, jumpref is not displaying under events tree hierarchy, we can write event for jumpref as discussed
in above.
Pattern 9: How to modify the data source field value in extension.

Pattern 10: how to access the members from data source methods.

You might also like