Customization in Dynamics 365 can be done using extension, which enables us to add functionality to existing code. Source code and metadata of model elements can be extended without an over-layering. In previous versions on Dynamics AX it did not seem like a big issue as over-layering was the only choice, and it was one of the key features. When we over-layer, the system copies the code into the packages layer and the developer makes changes to this copy. It is all seamless and has worked well in previous versions.

The problem is when we need to service the application, such as deploying a hotfix, we need to check for conflicts and potentially update our code. Also, if we have an ISV solution that over-layers a package, we will need an update from the ISV if the hotfix modifies an over-layered element. The solution Microsoft has is called extensibility. In this blog we will discuss how extension capability can be used to customize form using event handlers.

Before we start, is your team looking for a managed services partner to provide post go-live support, and preventative maintenance?

Extension Models and Packages

A package is nothing but a deployable unit that can become a distinct DLL. Usually a new project will be created in a new package and a new model. All new code can be placed in this model. This model is compiled into separate assembly. To create an extension model, go through the create model wizard and select Create new package on the second step.


Extension models have several advantages, including:

  • Application lifecycle management (ALM): Extension models simplify and improve the performance of deployments, builds, test automation and delivery to customers.
  • Design time performance: Building your model or project doesn't require you to recompile the entire application.
  • Servicing: In the cloud, Microsoft can install, patch, upgrade, and change internal APIs without affecting your customizations.
  • Upgrades: Unlike over-layering, extensions reduce the cost of upgrading to a new version, as this approach eliminates costly code and metadata conflicts.

The following diagram illustrates how extensions get isolated in their assemblies.


Form Extensions

The form extension works like any other extension; they are delta changes that are applied when the package is deployed. We can extend the functionality of a form by extending its controls and data sources. For example, in a form extension, we can:

  • Add a new control.
  • Enable or disable a control.
  • Change the text or label property of a control.
  • Change a control's visibility.
  • Change a form's help text.
  • Change a form's caption.
  • Add a new data source.
  • Change properties at the data-source level.
  • Add a form part.

In Microsoft Dynamics AX 2012, you could override form methods. In the current version, you use extensions to implement event handlers that are called from the base implementations of form methods.

Creating an Extension Class for Forms Code

To create an extension class for forms code, we can create a class which ends in _Extension. We only need to have the ExtensionOf decoration and ensure the name ends in _Extension. This capability made available with update 2 or platform 7.2.

So class declaration should read:

[ExtensionOf(formStr(FormName))]final class FormName_Extension{}

With extension classes we can add member variables, and these variables will be associated with the form. These variables can be referenced from any instance method. That way the state of the form can be maintained across different instance methods. Extension classes instantiate automatically; there is no access to private methods, but we can add state variables and access them along with forms public variables and methods.

The event handlers can be created as an instance methods. There are two types of event handler: a pre-event and post-event handler. Events are raised as preceding and succeeding operations around the base methods. We can write code to execute a before-base method or an after-base method. Microsoft Dynamics AX 2012 introduced XPP events, which are also available in this release and can be subscribed to in your extensions.

Events are exposed on the form designer on different elements, overridden methods and others.


  • Copy event handler method: This option copies a method signature to the clipboard. You can paste it in any X++ code editor to define a method that subscribes to the selected event.
  • Find event handlers: Searches and lists all methods subscribed to the selected event

Event Handler Methods Available with Form Datasource

An event handler method can be created on base datasource methods. All methods created will have FormDataSource _sender, FormDataSourceEventArgs _e as an argument.

Base methods can have preceding or succeeding events, but not all base methods have both events available. The following table shows events available with base datasource methods.


An argument of event handler can be used to get the FormDatasource, table record and formRun. Arguments can be manipulated and used in the following way:

Get formRun, Form control, datasource and selected record from form datasource

[FormDataSourceEventHandler(formDataSourceStr(MyForm, MyRandomTableDS), FormDataSourceEventType::Written)] public static void MyRandomTableDS_OnWritten(FormDataSource sender, FormDataSourceEventArgs e) { FormRun formRun = sender.formRun() as FormRun; // you can even call custom methods formRun.myCustomMethod();

// Get the selected datasource record TableName tableBuffer = sender.cursor();

// Get datasource variable FormDataSource DSVariable = sender.formRun().dataSource("TableName"); }

Event Handler Methods Available with Form Object Methods

The following event handler methods are available with form object methods:


An event handler method will have xFormRun as an argument. The following example shows how to get datasource, form control from xFormRun argument.

Get form datasource from xFormRun

[FormEventHandler(formStr(SomeForm), FormEventType::Initialized)] public static void SomeForm_OnInitialized(xFormRun sender, FormEventArgs e) { FormDataSource MyRandomTable_ds = sender.dataSource(formDataSourceStr(SomeForm, MyRandomTableDS)); ... }

Access form control from xFormRun

[FormEventHandler(formStr(SomeForm), FormEventType::Initialized)] public static void SomeForm_OnInitialized(xFormRun sender, FormEventArgs e) { // set the control to invisible as an example, MyControl)).visible(false); }

Event Handler Methods Available with Form Control Methods

The following event handler methods are available with form control methods:


Following example shows how we can get formRun from ‘FormControl’ argument, we can custom method with formRun. Datasource and current record can be obtained depending upon functionality we are working on.

Get FormRun from form control

[FormControlEventHandler(formControlStr(MyForm, MyButton), FormControlEventType::Clicked)] public static void MyButton_OnClicked(FormControl sender, FormControlEventArgs e) { FormRun formRun = sender.formRun() as FormRun; formRun.myCustomMethod(); }

Get current record in form control event

[FormControlEventHandler(formControlStr(SomeForm, SomeButton), FormControlEventType::Clicked)] public static void SomeButton_OnClicked(FormControl sender, FormControlEventArgs e) { // as an example the datasource number is used for access; I perceive the formDataSourceStr as more robust SomeTable callerRec = sender.formRun().dataSource(1).cursor(); }


Almost all customization can be done with extensions and event handlers in Dynamics 365 – there is no need to over-layer standard package. We have illustrated generic examples above, meanwhile more complex customizations can be done using event handlers.

For any questions on extension capabilities and event handlers in Dynamics 365 for Finance and Operations, please contact Hitachi Solutions today.