A workflow is essentially a structured business process that outlines the path a document takes within a system — specifying who needs to complete certain tasks, make decisions, or give approvals.
In D365 F&O, workflows can be configured directly in the application or developed within a dedicated development environment.
In this guide, we’ll walk through creating a workflow and its key components from the development side. These components include:
- Workflow categories
- Workflow approvals
- Manual and automated workflow tasks
- Workflow types
- Flow-control elements
- Providers
Creating the Required Elements for a New Workflow Type
When building a new workflow type in Microsoft Visual Studio, you’ll typically use the Workflow Type Wizard. This wizard will prompt you to provide several foundational elements before it can generate the workflow structure. These include:
- Workflow Category – Defines the functional module where the workflow will be available.
- Query – Retrieves data from the document table.
- Document Menu Item – Links to the form that represents your document. (Requires that the table and form already exist.)
Follow these steps to create each element:
Step-by-Step Setup
- In Solution Explorer, right-click your solution and select Add > New Project.
- Name the project MyWorkflow.
- In the project’s properties, set Synchronize Database to True (since you’ll be adding a new table).
- Right-click the project and choose Add > New Item.
- Navigate to Dynamics 365 Items > Business Process and Workflow.
- Select Workflow Category, name it MyWorkflowCategory, and click Add.
- Open the created category in Visual Studio Designer, set the Module to Inventory, and label it My workflow category.
Creating the Base Enum for Workflow Status
- Right-click the project, choose Add > New Item, then go to Data Types > Base Enum.
- Name the enum MyWorkflowStatus.
- Open the new enum, right-click, and choose New Element.
- Add these seven values (set both Name and Label):
- Submit
- Started
- Canceled
- Complete
- Denied (approval workflows)
- Change Requested (approval workflows)
- Returned (approval workflows)
Creating the Workflow Table
- Add a new table named MyWorkflowTable.
- Add the following Extended Data Types to its fields:
- Num
- Description
- MyWorkflowStatus (the Base Enum created earlier) — set Allow Edit to No.
- Save the table.
Creating the Workflow Form
- Add a new form named MyWorkflowTableForm.
- Drag MyWorkflowTable into the Data Sources node.
- Apply the Custom pattern to the form.
- Add a new Action Pane.
- Add a Grid to the form.
- From the data source fields, drag Num, Description, and MyWorkflowStatus into the grid. Save the form.
Creating the Display Menu Item
- Add a Display Menu Item named MyWorkflowTableForm.
- Point its Object property to the form MyWorkflowTableForm.
- Set the Label to My workflow. Save it.
Adding the Menu Extension
- In Application Explorer, locate the InventoryManagement menu under User Interface.
- Right-click and select Create Extension (ensure your project references ApplicationSuite).
- Open the new menu extension in Designer.
- Under InquiriesAndReports, drag the Display Menu Item from your project into the menu node. Save.
Creating the Workflow Query
- Add a new Query named MyWorkflowTableQuery.
- Drag MyWorkflowTable into the Data Sources node of the query.
- In the properties for the data source, set Dynamic Fields to Yes and save.
Creating the Workflow Type
Now that all the prerequisite elements are ready, you can proceed with creating the workflow type itself.
- In your project, right-click and select Add > New Item.
- Navigate to Business Process and Workflow.
- Choose Workflow Type and name it MyWorkflowType. This will launch the Workflow Type Wizard.
- In the wizard, fill in the fields with the elements you created earlier:
- Category —
MyWorkflowCategory
- Query —
MyWorkflowTableQuery
- Document menu item —
MyWorkflowTableForm
- Category —
- Click Next to proceed.

Finalizing the Workflow Type Setup
Once you click Next in the wizard, the Preview window will display all artifacts that will be generated — such as classes and menu items.
Click Next again to create these components. When the Add New Items dialog appears a second time, simply select Cancel to close it.
At this stage, several new elements will have been added to your project.
Update Action Menu Item Labels
Locate the two newly generated Action Menu Items and update their labels as follows:
- CancelMenuItem → set the label to Cancel
- SubmitMenuItem → set the label to Submit
Save all changes.
/// <summary>
/// The MyWorkflowTypeSubmitManager menu item action event handler.
/// </summary>
public class MyWorkflowTypeSubmitManager
{
public static void main(Args args)
{
// TODO: Write code to execute once a work item is submitted.
MyWorkflowTable myWorkflowTable;
WorkflowComment note = "";
WorkflowSubmitDialog workflowSubmitDialog;
WorkflowCorrelationId workflowCorrelationId;
WorkflowTypeName workflowTypeName = workFlowTypeStr('MyWorkflowType');
// Use WorkflowSubmitDialog to create a dialog.
workflowSubmitDialog = WorkflowSubmitDialog::construct(args.caller().getActiveWorkflowConfiguration());
workflowSubmitDialog.run();
if (workflowSubmitDialog.parmIsClosedOK())
{
myWorkflowTable = args.record();
note = workflowSubmitDialog.parmWorkflowComment();
try
{
ttsbegin;
workflowCorrelationId = Workflow::activateFromWorkflowType(workflowTypeName, myWorkflowTable.RecId, note, NoYes::No);
myWorkflowTable.MyWorkflowStatus = MyWorkflowStatus::Submit;
myWorkflowTable.update();
ttscommit;
info("Workflow submitted.");
}
catch (Exception::Error)
{
error("Workflow error.");
}
}
args.caller().updateWorkFlowControls();
}
}
Each workflow status can be managed through the workflow event handler class by calling a helper method that updates the Status
field in your workflow table.
To add this helper method:
- In Visual Studio, open the
MyWorkflowTable
object in Designer. - Right-click it and select View Code to open the table’s code editor.
- Add the following public static method to update the workflow status for a specific
RecId
:
public class MyWorkflowTable extends common
{
public static void updateWorkflowStatus(RefRecId _recId , MyWorkflowStatus _status)
{
MyWorkflowTable myWorkflowTable;
ttsbegin;
select forupdate myWorkflowTable
where myWorkflowTable.RecId == _recId;
if (myWorkflowTable)
{
myWorkflowTable.MyWorkflowStatus = _status;
myWorkflowTable.update();
}
ttscommit;
}
}
Go to the workflow table (MyWorkflowTable), and then right-click the Methods node to open the context menu.
Select Override, and then select the canSubmitToWorkflow
method. The method should return a status of True so that you can submit the workflow. The system should now allow you to submit all incomplete workflows.
/// <summary>
/// Can workflow be submitted.
/// </summary>
/// <param name = "_workflowType"></param>
/// <returns></returns>
public boolean canSubmitToWorkflow(str _workflowType = '')
{
boolean ret;
ret = super(_workflowType);
if (this.MyWorkflowStatus != MyWorkflowStatus::Complete)
{
ret = true;
}
else
{
ret = false;
}
return ret;
}
Select Save all and then build the project.
Open the event handler
class for the workflow type (MyWorkflowTypeEventHandler). The class has event methods for started, canceled, and completed. Call the method for updating the status on the table, as follows:
/// <summary>
/// The MyWorkflowTypeEventHandler workflow event handler.
/// </summary>
public class MyWorkflowTypeEventHandler implements WorkflowCanceledEventHandler,
WorkflowCompletedEventHandler,
WorkflowStartedEventHandler
{
public void started(WorkflowEventArgs _workflowEventArgs)
{
// TODO: Write code to execute once the workflow is started.
MyWorkflowTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),MyWorkflowStatus::Submit);
}
public void canceled(WorkflowEventArgs _workflowEventArgs)
{
// TODO: Write code to execute once the workflow is canceled.
MyWorkflowTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),MyWorkflowStatus::Canceled);
}
public void completed(WorkflowEventArgs _workflowEventArgs)
{
// TODO: Write code to execute once the workflow is completed.
MyWorkflowTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),MyWorkflowStatus::Complete);
}
}
Save all changes and rebuild the project.
The system will now generate the workflow type. To configure its properties, open MyWorkflowTableForm.
In the FormDesign properties, fill in the following fields:
- Title Data Source —
MyWorkflowTable
- Workflow Data Source —
MyWorkflowTable
- Workflow enabled —
Yes
- Workflow Type —
MyWorkflowType
Save all changes once again, and rebuild the project with synchronization enabled.
Your workflow type is now fully created.
Creating a Workflow Approval
After defining your workflow type, the next step is to create a workflow approval.
Before you begin, ensure the following prerequisites are met:
- Document type — Generated automatically when you created the workflow type.
- Document preview field group — You will need to create a new field group in the table (explained below).
- Document menu item — Already created earlier in the process.
Adding a Preview Field Group to the Table
- In Visual Studio Designer, open the
MyWorkflowTable
table and navigate to the Field Groups node. - Right-click Field Groups and choose New Group, naming it Workflow.
- Move your three table fields into this new field group.
- Save all changes and rebuild the project.
With the field group in place, you can now create the workflow approval.
Creating the Workflow Approval — D365 F&O
- Right-click your project and choose Add > New Item.
- Go to Business Process and Workflow, select Workflow Approval, and name it MyWorkflowApproval.
- In the Workflow Approval Wizard, provide the following details:
- Workflow document — The document generated with the workflow type (
MyWorkflowTypeDocument
) - Document preview field group — The
Workflow
field group you just created - Document menu item — The menu item used for your form in the workflow type (
MyWorkflowTableForm
) - Enable Deny outcome — Leave this option as it is
- Workflow document — The document generated with the workflow type (
- Click Next to proceed to the Workflow Approval configuration page.

- Select Next to have the system create all classes and menu items or select Cancel to close the window. The system adds the classes and menu items to your project, but you must modify it.
- Open your workflow approval event handler class from the project MyWorkflowEventHandler.
- For each status, update your table. The following code example calls the
updateWorkflowStatus
method for each event to update its status in the table.
public void started(WorkflowElementEventArgs _workflowElementEventArgs)
{
// Executes when the workflow approval step begins.
MyWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), MyWorkflowStatus::Started);
}
public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)
{
// Executes when the workflow approval step is canceled.
MyWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), MyWorkflowStatus::Canceled);
}
public void completed(WorkflowElementEventArgs _workflowElementEventArgs)
{
// Executes when the workflow approval step is successfully completed.
MyWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), MyWorkflowStatus::Complete);
}
public void denied(WorkflowElementEventArgs _workflowElementEventArgs)
{
// Executes when the workflow approval step is denied.
MyWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), MyWorkflowStatus::Denied);
}
public void changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)
{
// Executes when a change is requested in the workflow.
MyWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), MyWorkflowStatus::ChangeRequested);
}
public void returned(WorkflowElementEventArgs _workflowElementEventArgs)
{
// Executes when the workflow approval step is returned to a previous stage.
MyWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), MyWorkflowStatus::Returned);
}
public void created(WorkflowWorkItemsEventArgs _workflowWorkItemsEventArgs)
{
// Executes when workflow work items are created.
}
Save all changes.
Setting Labels for Workflow Approval Action Menu Items
For each workflow approval action menu item, you’ll need to set the Label property:
- Open the Approve action menu item (
MyWorkflowApprovalApprove
) in Visual Studio Designer and set its label to Approve.
Save all changes and close the menu item. - Open the Delegate action menu item (
MyWorkflowApprovalDelegateMenuItem
) and set its label to Delegate.
Save all changes and close. - Open the Reject action menu item (
MyWorkflowApprovalReject
) and set its label to Reject.
Save all changes and close. - Open the Request Change action menu item (
MyWorkflowApprovalRequestChange
) and set its label to Request change.
Save all changes and close. - Open the Re-submit action menu item (
MyWorkflowApprovalResubmit
) and set its label to Re-submit.
Save all changes and close.
Linking the Workflow Type to the Workflow Approval
- Open the workflow type (
MyWorkflowType
) in Visual Studio Designer. - In the Supported Elements node, right-click and choose New Workflow Element Reference.
- In the Properties window, set both Element Name and Name to
MyWorkflowApproval
. - At the top node of
MyWorkflowType
, change the Label property to My workflow type. - Save all changes and rebuild the project with synchronization enabled.
You’ve now finished the entire workflow development process.
Testing the Workflow — D365 F&O
Before you can test your workflow in Finance and Operations apps, it must be activated.
Since this workflow belongs to the Inventory module, follow these steps:
- Go to Inventory Management > Setup > Inventory management workflows.
- Click New — a window will appear listing all available workflows for this module.
- Select your workflow type (My workflow type), click Open, and run the application.
- Enter your username and password for authentication.
- When the application opens, locate the Workflow Designer (it may appear behind the main window in the taskbar).
- In Basic Settings, enter a placeholder name such as My workflow, then close the Basic Settings window.
- From the toolbox, drag MyWorkflowApproval into the workflow, placing it under Start.
- Connect Start → MyWorkflowApproval → End.
- Double-click MyWorkflowApproval to open its configuration.
- Select Step 1 and fill in the Basic Settings with descriptive text and instructions.
- Go to Assignments, choose User, then open the User tab.
- Select Admin as the assigned user and click Close.

- Select Save and close (shrink the window so you can find it in the lower part), and then enter Version notes.
- Select Activate the new version, and in Inventory management workflows, find your workflow.
- Under Manage, select Versions.
- Verify that your workflow is active. If it’s not, select Active to activate it. Finance and operations apps should show your workflow as activated, and a new action should appear in the form

Learn more about our services here.
Learn more about here.
Step-by-Step: Building a Custom Workflow in D365 F&O Using X++